您的位置:首页 > 其它

LeetCode Recover Binary Search Tree

2014-12-22 10:47 399 查看
题目

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;
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: