99. 恢复二叉搜索树
一开始想了好久没有什么好思路,去网上搜了一下,原来是中序遍历。
二叉搜索树的中序遍历是个(递增)有序数列,利用这个特性,我们可以很巧妙的解决这个题。
先看第二个例子,中序遍历后是:13245,观察发现只有一处发生了降序,只在第二位与第三位发生了降序情况,说明这两个数为异常数,交换3和2的位置重新中序遍历:12345
第一个例子,中序遍历是:321,观察发现有两处发生了降序,第一到第二位,以及第二到第三位,这种情况下交换第一位与第三位即可
实际上题目中只有两个节点被交换了,所以降序情况最多也只会出现两处。所以分两种情况处理即可。
我们再造个例子,看的更直观点:
[10 17 15 1 8 12 5]
中序遍历
1 17 8 10 12 15 5
17与3发生了降序,15与5发生了降序,我们将第一个降序的前一个元素与第二个降序的后一个元素,进行交换即可。
当只有一次降序出现时(可以理解为两个降序挤到了一块嘛),降序的前一个元素与降序的后一个元素,进行交换即可。
代码
class Solution {
TreeNode p, q, last;
void middle(TreeNode root) {
if (root == null) return;
middle(root.left);
if (last != null && last.val > root.val) {
if (p == null) p = last;
q = root;
}
last = root;
middle(root.right);
}
public void recoverTree(TreeNode root) {
middle(root);
int tmp = p.val;
p.val = q.val;
q.val = tmp;
}
}