Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Example 1:
Input: [1,3,null,null,2]
1
/
3
\
2
Output: [3,1,null,null,2]
3
/
1
\
2
二叉搜索树,其中两个节点发生了对换,导致不再是二叉搜索树,要求复原二叉搜索树
二叉搜索树的条件,左子树的值 < root的值 < 右子树的值
思路:
如果用中序遍历二叉搜索树,结果应该是升序的
如果其中出现了违反升序的节点,就说明找到了发生对换的节点
注意题中说只对换了2个element,所以就比较简单一些
比如正常顺序:
1,2,3,4,5,6
而现在中序遍历得到
1,5,3,4,2,6
2本来应该在第2个位置,现在换到第5个,2本来比3小,因为正常应该是升序的,所以也就比3后面的都小,想找到2的位置,只需要找到最后一个前一节点>后一节点的位置
想找到5的位置,只需要找到第一个发生倒序的位置
如果是相邻node交换,那后面应该一路都是升序的,如果后面再次出现降序(倒序),说明前面较小的节点换到后面去了,要换回来,
简而言之,就是要把第一次降序的第一个节点的值,和最后一次降序的第二个节点的值交换。
因为只需要记前后两节点,所以用一个pre记前一个节点,root为当前节点。
*注意java语言是按值传参数的,如果把TreeNode通过参数传递到函数内部,即使函数内部值改变,外部的值也还是不变,所以保存第一个倒序和最后一个倒序的TreeNode节点的定义放在class的global变量
class Solution {
TreeNode pre;
TreeNode first;
TreeNode second;
public void recoverTree(TreeNode root) {
inOrder(root);
//swap val
int tmp = first.val;
first.val = second.val;
second.val = tmp;
}
//找到第一次降序的第一个node,和最后一次降序的第二个node
void inOrder(TreeNode root) {
if(root == null) return;
inOrder(root.left);
//pre是前一个root,出现降序
if(pre != null && pre.val > root.val) {
if(first == null) { //第一次降序
first = pre;
}
second = root; //每次降序都记下第二个元素
}
pre = root;
inOrder(root.right);
}
}