recover-binary-search-tree(恢复二叉搜索树)

https://www.nowcoder.com/practice/67c7172122b54b748e78eac7b183b5f3?tpId=46&tqId=29079&tPage=4&rp=4&ru=/ta/leetcode&qru=/ta/leetcode/question-ranking

思路一(不满足题目要求的做法):二叉搜索树有一个特性,就是他的左孩子的节点的值比根节点的值小,右孩子的节点的值比根节点的大,所以我们在中序遍历二叉搜索数的时候会得到一个升序的序列。题目说节点被交换了。不管他交换了多少个节点,我们先把其中序遍历的结果储存到一个数据容器里面去,然后对这个数据容器的数字从小到大排序。排序后就中序遍历原来的二叉搜索树,然后把数据容器的每一个数字赋值到原来的树中。既然要这个数据容器的数据是有序的状态,那么直接用优先队列就好啦。


class Solution {
public:

	//优先队列储存二叉搜索树中序遍历的结果
	priority_queue <int , vector<int>, greater<int> >temp;
    void recoverTree(TreeNode *root) {
        
		if(root == nullptr)
			return ;
		dfs(root);//中序遍历树
		modify(root);
		return ;

    }

	void dfs(TreeNode * root)
	{
		if(root)
		{
			dfs(root -> left);
			temp.push (root->val);//把节点的值放到优先队列,队列会对值自动排序
			dfs(root -> right);
		}
	}

	void modify(TreeNode * root)//修改原来的二叉树。
	{
		if(root)
		{
			modify(root -> left);//修改左子树

			root -> val = temp.top ();//把值黏贴回来正确的位置
			temp.pop();//准备黏贴下一个数值
			modify(root -> right);//修改右子树
		}
	}
};

思路二:

可以发现一正常二叉搜索树中序遍历的结果是升序的。那么如果交换了节点,则中序遍历的结果就不是升序 的,则一定存在逆序对!比如下面这个交换了节点的图

中序遍历的结果是7 5 6 4 ,是4 和7的位置交换错了。

正常的顺序是4 5 6 7 ,可看到只要找到中序遍历结果的 逆序对 的位置,那就可以确认交换节点的位置。

可以用一个指针first指向第一逆序对的位置,second指向第二个逆序对的位置。

pre指向中序遍历的当前节点的前驱节点。

如果发现当前节点和前驱节点是pre-val> root->val(root是当前节点),那么就可以确认一个逆序对的出现位置。

 

最后交换first,和second指针所指的值即可。


class Solution {
public:

	//first指向第一个逆序对的位置,
	//second指向第二个逆序对的位置
	//pre指向中续遍历的前驱节点
	TreeNode * first , *second, *pre;

	Solution()//构造初始化
	{

		first = nullptr;
		second = nullptr;
		pre = nullptr;
		
	}

	void  swap(int & a, int & b)
	{
		a = a ^ b;
		b = a ^ b;
		a = a ^ b;
	}
    void recoverTree(TreeNode *root) {
        
		if(root == nullptr)
			return ;

		
		dfs(root);

		//cout<<"check p : "<<bool(first)<<" "<<bool(second)<<endl;
		if(first && second )
			swap(first->val, second->val);

		return ;
    }

	void dfs(TreeNode * root)
	{
		if(root )
		{
			dfs(root -> left);//中序遍历

			if(!pre)//前驱节点的起始
				pre = root;
			
			else
			{
				if( pre && pre->val > root->val )//找到逆序对
				{
					if(first == nullptr)//记录第一个逆序对出现的位置
						first = pre;
					
					second = root;//记得直接复制啊,当树只有两个节点的时候
					//且节点位置交换了之后这个第二个交换的节点位置就是当前节点了
					//比如【0 1 # # #】这二叉树

				}
			}

			pre = root;//前驱节点变为当前节点

			dfs(root -> right);//遍历右子树


		}
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值