Recover Binary Search Tree ~ Leetcode

交换两个元素修正 BST

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


class Solution
{
public:
    void inOrder(TreeNode* root, vector& Tnode, vector& 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 Tnode;
        vector Tval;
        inOrder(root, Tnode, Tval);
        sort(Tval.begin(), Tval.end());
        for (int i = 0; i < Tnode.size(); ++i)
        {
            Tnode[i]->val = Tval[i];
        }
    }
};

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

Mirrors 遍历

如果需要 的空间复杂度, 可以使用 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

你可能感兴趣的:(Recover Binary Search Tree ~ Leetcode)