|
10 | 10 |
|
11 | 11 | public class RecoverBinarySearchTree {
|
12 | 12 |
|
13 |
| - private TreeNode first, second, prev; |
| 13 | + TreeNode first, second, prev; |
14 | 14 |
|
15 |
| - /** |
16 |
| - * TestCase |
17 |
| - * [0, 1]是最重要且易错的 |
18 |
| - */ |
19 | 15 | public void recoverTree(TreeNode root) {
|
20 |
| - if (root == null) { |
21 |
| - return; |
22 |
| - } |
23 |
| - inorderTraversal(root); |
24 |
| - int t = first.val; |
| 16 | + inorder(root); |
| 17 | + int val = first.val; |
25 | 18 | first.val = second.val;
|
26 |
| - second.val = t; |
| 19 | + second.val = val; |
27 | 20 | }
|
28 | 21 |
|
29 |
| - // 首先first是可以一次性确定的,second不能,可能要被多次覆盖,所以 |
30 |
| - // 下面设置了second后没有立即终止,而是继续遍历,直到最后的那个才是真正的 |
31 |
| - private void inorderTraversal(TreeNode node) { |
32 |
| - if (node == null) { |
33 |
| - return; |
34 |
| - } |
35 |
| - |
36 |
| - inorderTraversal(node.left); |
37 |
| - |
38 |
| - if (prev != null) { |
39 |
| - // 两个节点交换,肯定是大的放前面了,小的放后面了,所以遇到的第一个prev大于node的,first肯定是prev. |
40 |
| - // 遇到的第一个node小于prev的,second肯定是node |
41 |
| - if (first == null && prev.val > node.val) { |
42 |
| - first = prev; |
43 |
| - } |
44 |
| - |
45 |
| - // 这里可否换成second == null,不能,因为second要多次覆盖 |
46 |
| - if (first != null && prev.val > node.val) { |
47 |
| - second = node; |
48 |
| - // 这里可否加上break |
| 22 | + private void inorder(TreeNode root) { |
| 23 | + while (root != null) { |
| 24 | + if (root.left == null) { |
| 25 | + detect(root); |
| 26 | + root = root.right; |
| 27 | + } else { |
| 28 | + TreeNode pre = root.left; |
| 29 | + for ( ; pre.right != null && pre.right != root; pre = pre.right); |
| 30 | + if (pre.right == null) { |
| 31 | + pre.right = root; |
| 32 | + root = root.left; |
| 33 | + } else { |
| 34 | + pre.right = null; |
| 35 | + detect(root); |
| 36 | + root = root.right; |
| 37 | + } |
49 | 38 | }
|
50 |
| - |
51 |
| - // 以上两个if为何可能同时满足,参考[0,1] |
52 | 39 | }
|
53 |
| - |
54 |
| - prev = node; |
55 |
| - |
56 |
| - inorderTraversal(node.right); |
57 | 40 | }
|
58 | 41 |
|
59 |
| - |
60 |
| - // 可换成非递归的写法 |
61 |
| - private void inorderTraverse(TreeNode root) { |
| 42 | + private void inorder2(TreeNode root) { |
62 | 43 | Stack<TreeNode> stack = new Stack<>();
|
63 |
| - |
64 | 44 | while (!stack.isEmpty() || root != null) {
|
65 | 45 | if (root != null) {
|
66 | 46 | stack.push(root);
|
67 | 47 | root = root.left;
|
68 | 48 | } else {
|
69 | 49 | root = stack.pop();
|
70 |
| - |
71 |
| - if (prev != null) { |
72 |
| - if (first == null && root.val < prev.val) { |
73 |
| - first = prev; |
74 |
| - } |
75 |
| - |
76 |
| - if (first != null && root.val < prev.val) { |
77 |
| - second = root; |
78 |
| - } |
79 |
| - } |
80 |
| - |
81 |
| - prev = root; |
82 |
| - |
83 |
| - root = root.right; |
84 |
| - } |
85 |
| - } |
86 |
| - } |
87 |
| - |
88 |
| - private void inorderTraverse2(TreeNode root) { |
89 |
| - TreeNode temp; |
90 |
| - |
91 |
| - while (root != null) { |
92 |
| - if (root.left == null) { |
93 |
| - helper(root); |
| 50 | + detect(root); |
94 | 51 | root = root.right;
|
95 |
| - } else { |
96 |
| - temp = root.left; |
97 |
| - while (temp.right != null && temp.right != root) { |
98 |
| - temp = temp.right; |
99 |
| - } |
100 |
| - if (temp.right == null) { |
101 |
| - temp.right = root; |
102 |
| - root = root.left; |
103 |
| - } else { |
104 |
| - temp.right = null; |
105 |
| - helper(root); |
106 |
| - root = root.right; |
107 |
| - } |
108 | 52 | }
|
109 | 53 | }
|
110 | 54 | }
|
111 | 55 |
|
112 |
| - private void helper(TreeNode node) { |
| 56 | + private void detect(TreeNode node) { |
113 | 57 | if (prev != null) {
|
114 | 58 | if (first == null && prev.val > node.val) {
|
115 | 59 | first = prev;
|
|
0 commit comments