Leetcode
-99
题目描述
You are given the root of a binary search tree (BST), where exactly two nodes of the tree were swapped by mistake. Recover the tree without changing its structure.
Follow up: A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
Example 1:
Example 2:
题目分析
这道题的题意是重建二叉搜索树,即题目给定了交换了两个节点的二叉搜索树,而我们需要找出这两个节点,交换他们的顺序,将BST归位。
对于BST,我们运用最多的性质是BST的中序遍历可以得到一个有序数组。那么不妨将打乱的BST和它本来的BST中序差别,从而找到结题的思路。
首先构造如下的两个树,左边为打乱后的树,右边为恢复的二叉树。
中序遍历上图
left: 1 4 3 2 7
right: 1 2 3 4 7
结合图像,很容易发现,是2和4两个节点的顺序反了。那么剩下的问题就是怎么定位这两个数了。通过,观察中序遍历的结果,可依发现,位置正确的元素是升序的。那么我们从左到右来看这些元素的前后大小关系,首先4>3,那么4就没有在正确的位置。同时,3>2,但是注意这里不是3的位置不对,因为第一反序的数是把较大数放到了靠前(相对于它本来的位置),所以第二个数就是把较小的数放到了靠后的位置,这里我们记录下2的位置是错的。分析到这里就有了清晰的思路了,接下来将其实现一下。
尝试对上面这一段话进行总结一下,感觉说的有点啰嗦。总结:这道题我们需要找到两个数,大数被放到了靠前的位置,小数被放到了靠后的位置。找到两个乱序的对(pair),前一个取较大的数的位置,后一个取较小数的位置。
哈哈哈还是很啰嗦,希望能看懂~
算法实现
TreeNode* first = NULL;
TreeNode* second = NULL;
TreeNode* prev = NULL;
// 初始化变量
void recoverTree(TreeNode* root) {
if (!root) { // 空树直接返回
return ;
}
inorder(root);
// 下面是对换位的数进行归位操作
int temp = first->val;
first->val = second->val;
second->val = temp;
}
// 确定first和second的位置
void inorder(TreeNode* root) {
if (!root) {
return ;
}
inorder(root->left);
if (first == NULL && (prev == NULL || root->val < prev->val)) {
first = prev; // 这里被执行两次,第一次:first = null,第二次是找到较大数的位置
}
if (first != NULL && root->val < prev->val) {
second = root; // 找到较小数的位置
}
prev = root;
inorder(root->right);
}