題目:
二叉搜索樹中的兩個節點被錯誤地交換。
請在不改變其結構的情況下,恢復這棵樹。
理解題目:
意思就是說給的二叉搜索樹中有兩個結點是被交換的,我們要做的就是把這兩個找到,然後對他們進行交換。
思路:
二叉搜索樹的中序遍歷是一個遞增的序列,但是,因爲被錯誤交換了兩個結點,所以這個中序序列有兩個值我們要將它找出來,然後將它們交換就可以。
子問題:如何得到中序序列
- 可以通過遞歸算法
- 可以通過Morris 算法(即線索二叉樹)
子問題:如何找到這兩個被錯誤交換的結點
- 兩個被交換的結點是相鄰的
- 兩個被交換的不是相鄰的
子問題:如何在樹中交換兩個結點的值。
public void recoverTree(TreeNode root) {
if (root == null)
return;
List<Integer> list = new LinkedList<>();
inorder(root, list);
int x = -1;
int y = -1;
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i) > list.get(i + 1)) {
if (x == -1)
x = list.get(i);
y = list.get(i + 1);
}
}
swap(root, x, y);
}
private void swap(TreeNode root, int x, int y) {
if (root != null && (root.val == x || root.val == y))
root.val = root.val == x ? y : x;
swap(root.left, x, y);
swap(root.right, x, y);
}
public void inorder(TreeNode root, List<Integer> list) {
if (root == null)
return;
inorder(root.left, list);
list.add(root.val);
inorder(root.right, list);
}