题目地址:
https://leetcode.com/problems/recover-binary-search-tree/
给定一棵二叉树,交换其恰好两个节点就可以使之成为一棵BST。要求交换那两个节点然后返回新树树根,不允许改变树的结构。要求空间 O ( 1 ) O(1) O(1)。
可以采用Morris中序遍历。交换两个节点之后,中序遍历的序列中可能会有一次下降(交换相邻位置数的情况),也可能会有两次下降(交换不相邻位置数的情况),设要交换的两个节点分别为 p p p和 q q q,那么先找到第一次下降的数对中第一个数,暂时将第二个数存入 q q q,如果发现第二次下降,则将第二次下降的数对中第二个数存入 q q q,最后只需要交换 p p p和 q q q即可。代码如下:
public class Solution {
public void recoverTree(TreeNode root) {
// prev记录中序遍历的前驱
TreeNode cur = root, prev = null, p = null, q = null;
while (cur != null) {
TreeNode left = cur.left;
if (left == null) {
if (prev != null && prev.val > cur.val) {
if (p == null) {
p = prev;
}
q = cur;
}
prev = cur;
cur = cur.right;
} else {
while (left.right != null && left.right != cur) {
left = left.right;
}
if (left.right == null) {
left.right = cur;
cur = cur.left;
} else {
left.right = null;
if (prev != null && prev.val > cur.val) {
if (p == null) {
p = prev;
}
q = cur;
}
prev = cur;
cur = cur.right;
}
}
}
swap(p, q);
}
void swap(TreeNode p, TreeNode q) {
int tmp = p.val;
p.val = q.val;
q.val = tmp;
}
}
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。