[LeetCode] 99. Recover Binary Search Tree

博客围绕恢复二叉搜索树展开,树中两个元素交换位置,需在不改变结构的情况下恢复。介绍了两种解法,解法1通过中序遍历保存节点和值,排序后赋值,空间复杂度O(n);解法2利用Morris遍历实现中序遍历,空间复杂度O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Recover Binary Search Tree

Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Example:

Input: [1,3,null,null,2]
1
/
3
\
2
Output: [3,1,null,null,2]
3
/
1
\
2

解析

直接交换两位置的节点值,重点在找到节点位置。
最简单的就是直接中序遍历整棵树,保存节点和节点值,对节点值进行排序,将排好序的节点值赋给节点。空间复杂度为O(n)。

解法1:空间复杂度O(n)

利用三个指针,分别为pre指向当前节点(即根节点)的前驱节点,first指针指向第一个交换的地方,second指针指向第二个交换的地方,利用中序遍历得到两个指针,并交换节点值。
例子:
假设中序遍历为163452,需要交换的为2和6,首先pre=1,root从1往后移:
当root=3时,pre=6,此时pre大于root,违反中序遍历的顺序,由于first初始为NULL,则令first=pre=6为第一个交换点,second=root(如果后续没有顺序错误这里second就是第二个交换点);
当root=2时,pre=5,违反同上,此时first不为NULL,second=root=2,中序遍历结束;
交换first=6和second=2的节点值。

class Solution {
public:
    TreeNode* pre, *first, *second;
    void recoverTree(TreeNode* root) {
        pre = first = second = NULL;
        inorder(root);
        if(first && second)
            swap(first->val, second->val);
    }
    void inorder(TreeNode* root){
        if(!root) return;
        inorder(root->left);
        if(!pre) pre = root;
        else{
            if(pre->val > root->val){
                if(!first) first = pre;
                second = root;
            }
            pre = root;
        }
        inorder(root->right);
    }
};

解法2:空间复杂度O(1)

利用Morris遍历来实现中序遍历的O(1)空间复杂度,Morris遍历算法具体步骤查看Binary Tree Inorder Traversal
在解法1和Morris遍历的基础上增加一个指针记录上一个访问的节点。即总共有cur, pre, first, second, precur五个指针。

class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode *cur, *pre, *first, *second, *parent;
        first = second = parent = NULL;
        cur = root;
        while(cur){
            if(!cur->left){
                if(parent && parent->val > cur->val){
                    if(!first) first = parent;
                    second = cur;
                }
                parent = cur;
                cur = cur->right;
            }
            else{
                pre = cur->left;
                while(pre->right && pre->right != cur)
                    pre = pre->right;
                if(!pre->right){
                    pre->right = cur;
                    cur = cur->left;
                }
                else{
                    if(parent->val > cur->val){
                        if(!first) first = parent;
                        second = cur;
                    }
                    parent = cur;
                    pre->right = NULL;
                    cur = cur->right;
                }
            }
        }
        if(first && second) swap(first->val, second->val);
    }
};

参考

http://www.cnblogs.com/grandyang/p/4298069.html
Morris遍历,Binary Tree Inorder Traversal

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值