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?
题中提到,有两个点是被错误地swapped了。那么如果想要实现空间复杂度O(1)的算法,一个可行的方法就是找出这两个出错的点,然后把它们的值swap回来就可以了。
先看代码:
public class Solution {
private TreeNode firstAbnor = null;
private TreeNode secondAbnor = null;
private TreeNode lastNode = new TreeNode(Integer.MIN_VALUE);
public void recoverTreeHelper(TreeNode root) {
if(root == null) {
return;
}
recoverTreeHelper(root.left);
if (firstAbnor == null && root.val < lastNode.val) {
firstAbnor = lastNode;
}
if (firstAbnor != null && root.val < lastNode.val) {
secondAbnor = root;
}
lastNode = root;
recoverTreeHelper(root.right);
}
public void recoverTree(TreeNode root) {
recoverTreeHelper(root);
int tmp = firstAbnor.val;
firstAbnor.val = secondAbnor.val;
secondAbnor.val = tmp;
}
}
首先看public void recoverTreeHelper(TreeNode root) 这个 helper function。这个方程的功能就是找到上面说的那两个出错的点。
对于这个方程,如果抛去其他的部分不看,可以抽象为如下这些:
public void recoverTreeHelper(TreeNode root) {
if(root == null) {
return;
}
recoverTreeHelper(root.left);
// ... do something
lastNode = root;
recoverTreeHelper(root.right);
}
这么一看就很明朗了,这就是一个递归的树的中序遍历。中序遍历是保证遍历的值是递增的。
那么如果在遍历的过程中碰上不符合递增顺序的,显然就是出错的值。这就是那两个 if() 判断语句的职责,判断出不符合递增的点,记录在firstAbnor和secondAbnor里,对应找到的两个不符合顺序的点。
lastNode就跟前一篇文章 flatten中的方法一样,记录的其实就是在中序遍历中,当前访问节点的之前一次访问的节点