99 恢复二叉搜索树

题目描述:
二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。

示例 1:
输入: [1,3,null,null,2]
示例 2:
在这里插入图片描述
进阶:
使用 O(n) 空间复杂度的解法很容易实现。
你能想出一个只使用常数空间的解决方案吗?

方法1:
主要思路:
(1)使用中序遍历一个二叉搜索树,应该获得的是一个有序的序列,当交换了两个值之后,会在遍历的过程中,出现两次不符合次序的情形,记录这两次中应该交换的位置即可;
(2)这里使用了迭代的方法中序遍历,保存需要交换的两个结点;
(3)为了能够比较前后两个结点的值,这里需要保存前一个结点的地址;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void recoverTree(TreeNode* root) {
        stack<TreeNode*> st;//使用栈实现中序遍历的迭代方法
        //存储两个需要交换的结点的位置
        TreeNode* x=nullptr;
        TreeNode* y=nullptr;
        //存储当前结点的上一个结点
        TreeNode* pre=nullptr;
        //迭代的中序遍历
        while(!st.empty()||root!=nullptr){
            while(root){
                st.push(root);
                root=root->left;
            }
            root=st.top();
            st.pop();
            //遍历过程中判断需要交换的位置
            if(pre!=nullptr&&pre->val>root->val){
                x=root;
                if(y==nullptr){//获得第二次的位置后可以直接跳出循环
                    y=pre;
                }
                else{
                    break;
                }
            }
            pre=root;//保存上一个结点的位置
            root=root->right;
        }
        swap(x->val,y->val);//交换两个结点的位置
    }
};

方法2:
主要思路:
(1)使用递归实现上述思路;
(2)指针的直接使用成员变量进行操作;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* x=nullptr;
    TreeNode* y=nullptr;
    TreeNode* pre=nullptr;

    void helper(TreeNode* root,bool& sign){
        if(sign||root==nullptr){
            return;
        }
        helper(root->left,sign);
        if(pre!=nullptr&&pre->val>root->val){
            //cout<<pre->val<<"   "<<root->val<<endl;
            x=root;
            if(y==nullptr){//获得第二次的位置后可以直接跳出循环
                 y=pre;
            }
            else{
                sign=true;
                return;
            }
        }
        pre=root;
        helper(root->right,sign);
        
    }

    void recoverTree(TreeNode* root) {
        
       
        bool sign=false;
        helper(root,sign);
        swap(x->val,y->val);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值