99. 恢复二叉搜索树

题目描述

给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
示例 2:
输入: [3,1,4,null,null,2]

  3
 / \66
1   4
   /
  2

输出: [2,1,4,null,null,3]

  2
 / \
1   4
   /
  3

进阶:
使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

思路

根据实际例子总结规律
按照中序遍历的方式,将这颗问题二叉搜索树的节点值排列起来,从左往右,我们遇到的第一个问题节点,是从后面被错误放到了前面,因为是从后面错放到了前面,所以针对第一个错误节点,它的异常情况是它的值大于它的下一个节点;而第二个问题节点是从前面被错误放到后面的,所以它的异常情况是它的值小于前一个值。
总结起来:
第一个错误节点,pre>cur(pre为错误节点)
第二个错误节点,pre>cur(cur为错误节点)
需要注意的是,相邻节点互换时,只会出现一次pre>cur的异常情况,而不相邻的节点互换时,会出现两次pre>cur的异常情况,设计程序时需要注意到这一点。

代码实现1

class Solution {
public:
void recoverTree(TreeNode *root) {
        //如果这个二叉搜索树是空树或者单节点树,则不需要
        //进行修正操作
        if(!root || (!root->left && !root->right))
            return;   	
    	TreeNode *p1 = nullptr;
    	TreeNode *p2 = nullptr;
    	TreeNode *pre = nullptr;
    	recoverTreeCore(root,pre,p1,p2);
        if(p1 && p2)
        {
        	int temp = p1->val;
        	p1->val = p2->val;
        	p2->val = temp; 
        }
    }
     
    void recoverTreeCore(TreeNode *root,TreeNode* &pre,TreeNode* &first,TreeNode * &second)
    {   
    	
        if(root == nullptr)
            return;
        //由于前面的递归终止条件,如果没有左节点,会直接返回
        recoverTreeCore(root->left,pre,first,second);
        //针对当前节点做的操作
    	if(pre!=nullptr &&  pre->val > root->val)//出现异常时发生的状态情形
    	{  //这个条件说明我们遇到的是第一个问题节点
    	   if(first == nullptr)
    		first = pre;
    	    second = root;
        }
    	pre = root; 

       recoverTreeCore(root->right,pre,first,second);
    	
    }

};

代码实现2

class Solution {
public:
    void recoverTree(TreeNode *root) {

        //如果这个二叉搜索树是空树或者单节点树,则不需要
        //进行修正操作
        if(!root || (!root->left && !root->right))
            return;
        TreeNode *p1 = nullptr;
        TreeNode *p2 = nullptr;
        TreeNode *pre = nullptr;
        //由cnt我们可以得知总共发生异常的次数,及交换的是相邻还是不相邻的元素这个信息
        int cnt = 0;
        recoverTreeCore(root,pre,p1,p2,cnt);
        if(p1!=nullptr && p2!=nullptr)
        {
            int temp = p1->val;
            p1->val = p2->val;
            p2->val = temp; 
        } 

    }
        //查找两个满足条件的结点,成功找到了要及时终止查找的进行,返回返回
        //一个布尔类型标识是否查找成功
    void recoverTreeCore(TreeNode *root,TreeNode* &pre,TreeNode* &first,TreeNode * &second,int &cnt)
    {   
        if(root->left!=nullptr)
            recoverTreeCore(root->left,pre,first,second,cnt);
        if(cnt == 2)
            return;
        if(pre!=nullptr &&  pre->val > root->val)//出现异常时会发生的状况
        {   
            cnt++;
            if(first == nullptr)
                first = pre;
            second = root;
        }
        pre = root;        
        if(cnt == 2)
            return;
        else
        {
            if(root->right!=nullptr)
                recoverTreeCore(root->right,pre,first,second,cnt);
        }

    }


};

posted on 2021-06-14 23:58  朴素贝叶斯  阅读(40)  评论(0编辑  收藏  举报

导航