Recover Binary Search Tree (恢复一棵二叉搜索树)

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

Recover the tree without changing its structure.

Note:
A solution using O( n) space is pretty straight forward. Could you devise a constant space solution?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

  题目大意是说在给定的二叉搜索树中有两个节点位置被交换了,把这个树恢复成原来的样子,要求空间复杂度O(1)
 这里我采用递归的方式 用两个指针first,second 表示这两个被交换了的节点,pre表示中序遍历访问的当前节点的前一个节点,递归调用结束first,second的内容交换一下就ok了。 具体思路比较简单 就是中序遍历一个二叉搜索树应该是一个递增的序列,如果首次发现前一个节点的值大于当前访问节点的值,那么前一个节点肯定是第一个被改变的位置,然后把当前访问节点设置为第二个被改变的位置,再继续中序遍历,如果之后再没有出现这样的情况(前一个访问的节点值大于当前的) 那么first,second就是所求节点位置,不然又找到了这样的情况,就把second指向第二个被改变的元素,最终first,second就是所求。


上图中找到first后first就不会在改变,second会改变1次,或者找到后就不变。


/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void recoverTree(TreeNode *root) {
        TreeNode *first = NULL, *second = NULL, *pre = NULL;
		bool flag = true;
		findMistake(root, pre, first, second, flag);
		int tmp = first->val;
		first->val = second->val;
		second->val = tmp;
    }

private: 
	void findMistake(TreeNode *root, TreeNode *&pre, TreeNode *&first, TreeNode *&second, bool &flag)
	{
		if (!root) return;
		if (root->left) findMistake(root->left, pre, first, second, flag);
		if (pre)
		{
			if (flag && pre->val > root->val)
			{
				first = pre;
				second = root;
				flag = false;
			}
			else if (!flag && pre->val > root->val)
			{
				second = root;
			}
		}
		pre = root;
		if (root->right) findMistake(root->right, pre, first, second, flag);
	}
};

之前没怎么用过TreeNode *&这种形式的形参,写程序的时候携程TreeNode * 结果发现指针总不会指向正确的节点,因为形参是传值调用,如果指针参数不是引用,实际也是传递一个指针的副本,之前本来想改成非递归的中序遍历,应该也能解决问题,不过室友说这种TreeNode *&是可以的 试了一下果然可以 于是就不写非递归的了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值