Recover Binary Search Tree ~ Leetcode

交换两个元素修正 BST

题目中说的很直观的 O(n) 的方法, 想到了一个。
BST 的中序遍历结果是递增的序列, 根据这个可以用两个向量分别保存中序遍历的节点,和节点的值,对值排序后赋给结点


class Solution
{
public:
    void inOrder(TreeNode* root, vector<TreeNode*>& Tnode, vector<int>& Tval)
    {
        if (!root) return;
        inOrder(root->left, Tnode, Tval);
        Tnode.push_back(root);
        Tval.push_back(root->val);
        inOrder(root->right, Tnode, Tval);
    }
    void recoverTree(TreeNode* root)
    {
        vector<TreeNode*> Tnode;
        vector<int> Tval;
        inOrder(root, Tnode, Tval);
        sort(Tval.begin(), Tval.end());
        for (int i = 0; i < Tnode.size(); ++i)
        {
            Tnode[i]->val = Tval[i];
        }
    }
};

因为只有两个节点错误,可以使用指针来省略两个vector, 不过一般的中序遍历(包括递归和使用栈的迭代法)本身需要O(h)的栈空间, 仍然不满足要求。

Mirrors 遍历

如果需要 O(1)的空间复杂度, 可以使用 Mirrors Traversal. 要理解这种方法, 可以通过线索二叉树(threaded binary tree)

线索二叉树

保存了每个节点前驱和后继的二叉树.

前驱: 某种遍历次序下该节点之前的节点
后继: 某种遍历次序下该节点之后的节点

对线索二叉树的遍历只需要从最先的节点一路访问后继就可以,不需要额外空间

Mirrors 遍历

通过暂时修改左右孩子指针,不需要新的指针域
具体步骤, 以中序遍历为例

  1. 初始化 cur 为 root
  2. 如果 cur 没有前驱(没有左孩子),访问当前节点, cur=cur->right
  3. 如果 cur 有左孩子
    1. 如果先左孩子,再向右走到空,将最右的叶子节点右孩子指向 cur (暂时修改了树的结构), cur=cur->left;
    2. 如果先左孩子,再向右走能回到 cur,将 cur 前驱的右孩子重新设为空(恢复树的结构)。输出当前节点。当前节点更新为当前节点的右孩子
  4. 如果 cur 不为空, 重复 2,3
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容