LeetCode Recover Binary Search Tree

题目

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

 

 

根据上一题的合法性判断,稍作修改,

记录限制元素的位置,可以寻找到不合法的位置,和与之冲突的位置。

 

 

根据交换的元素所处的位置,可以分为三种情况:

1、交换的两个位置在一个子树的左右分支上,任何一个元素都不在以另一个元素为根的子树上;

此时交换的这两个位置必然不合法,且是所在分支中不合法位置中深度最小的;

可以首先找到一个不合法的元素。去除以该位置为根的子树后,可找到第二个不合法的元素,交换两者即可。

2、交换的两个位置在一个子树上,一个为该子树的根,另一个在该子树的左子树上;

此时左子树上存在不合法位置,其与发生交换的子树的根冲突;

寻找到第一个不合法位置后,即可找到冲突的位置,即为其中一个交换位置;

另一个元素是第一个交换位置左子树中的最大元素,找到后交换即可;

3、交换的两个位置在一个子树上,一个为该子树的根,另一个在该子树的右子树上;

此时左子树合法,右子树上存在不合法位置,其与发生交换的子树的根冲突;

寻找到第一个不合法位置后,即可找到冲突的位置,即为其中一个交换位置;

另一个元素是第一个交换位置右子树中的最小元素,找到后交换即可;

 

代码:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
	struct dp	//探测用点
	{
		TreeNode *tn,*min,*max;	//当前位置,当前位置的下限所在位置,上限所在位置
		dp(TreeNode *t=NULL,TreeNode *mi=NULL,TreeNode *ma=NULL):tn(t),min(mi),max(ma){}
	};
	dp test(vector<dp> &sdp)	//dfs寻找不符合条件的点
	{
		int min,max;
		dp dp1;
		while(!sdp.empty())	//dfs
		{
			dp1=sdp.back();
			sdp.pop_back();
			min=dp1.min==NULL?INT_MIN:dp1.min->val;	//求限制的值
			max=dp1.max==NULL?INT_MAX:dp1.max->val;
			if(dp1.tn==NULL)
				continue;
			if(dp1.tn->val<=min||dp1.tn->val>=max)	//不符合要求则返回相应信息
			{
				return dp1;
				break;
			}
			sdp.push_back(dp(dp1.tn->right,dp1.tn->val>min?dp1.tn:dp1.min,dp1.max));	//更新限制
			sdp.push_back(dp(dp1.tn->left,dp1.min,dp1.tn->val<max?dp1.tn:dp1.max));
		}
		return dp();
	}
	TreeNode* find_min(TreeNode *root,TreeNode *min)	//寻找分支中最小值的点
	{
		if(root!=NULL)
		{
			if(root->val<min->val)
				min=root;
			min=find_min(root->left,min);
			min=find_min(root->right,min);
		}
		return min;
	}
	TreeNode* find_max(TreeNode *root,TreeNode *max)	//寻找分支中最大值的点
	{
		if(root!=NULL)
		{
			if(root->val>max->val)
				max=root;
			max=find_max(root->left,max);
			max=find_max(root->right,max);
		}
		return max;
	}
    void recoverTree(TreeNode *root) {
		dp first,second;	//记录不符合要求的点的位置
		TreeNode *tp;
		vector<dp> sdp;	//dfs用栈
		sdp.push_back(dp(root));	//压入根
		first=test(sdp);	//探测第一个
		if(first.tn==NULL)
			return;
		second=test(sdp);	//探测非第一个外的分支,找第二个
		if(second.tn!=NULL)	//存在,说明交换的位置在一个子树树的左右子树上,交换回来即可
		{
			cout<<"c1";
			swap(first.tn->val,second.tn->val);
			return;
		}
		sdp.clear();	//否则,说明交换的位置在一个子树上,其中一个交换位置是该子树的根
		int min=first.min==NULL?INT_MIN:first.min->val;
		int max=first.max==NULL?INT_MAX:first.max->val;
		if(first.tn->val<min)	//超下界,说明另一个交换的位置在分支的左子树上,寻找分支最小的位置,和冲突位置交换
		{
			tp=find_min(first.tn,first.tn);
			swap(first.min->val,tp->val);
			return;
		}
		if(first.tn->val>max)	//超上界,说明另一个交换的位置在分支的右子树上,寻找分支最大的位置,和冲突位置交换
		{
			tp=find_max(first.tn,first.tn);
			swap(first.max->val,tp->val);
			return;
		}
    }
};


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值