1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { private TreeNode lastVisited = null, x = null, y = null;
public void recoverTree(TreeNode root) { dfs(root); swap(x, y); }
private void dfs(TreeNode root) { if (root == null) { return; } dfs(root.left); if (lastVisited != null && root.val < lastVisited.val) { y = root; if (x == null) { x = lastVisited; } else { return; } } lastVisited = root; dfs(root.right); }
private void swap(TreeNode nodeOne, TreeNode nodeTwo) { int temp = nodeOne.val; nodeOne.val = nodeTwo.val; nodeTwo.val = temp; } }
|
这道题告诉我们在一个sorted list中, 两个元素交换了位置, 我们如何找到这两个元素的办法. 大致的思路就是被换到前面的大的数, 它的后一个数字肯定比自己小, 而换到后面的小数, 它比它的前一个小. 我们就利用这个特点来去找. 14行遇到现在比前一个数字小的情况, 那这有两种情况, 要么是我们先来到了换到前面的大数的后一个位置, 此时我们前一个位置就是大数; 或者是我们来到了小数的位置. 如何区别这两种情况呢? 我们统一认为我们现在是小数的位置, 让y = 现在的位置的数字. 然后看x是否有值, 如果有的话就说明之前已经找到了大数并存到了x中, 那么此时我们确实就是小数的位置, 直接return即可. 如果x是null, 那说明我们在大数后一个位置, 那么让x等于我们前一个位置的值, 此时还要继续找那个小数在哪里. 此时y存的值并一定是小数的值, 因为可能两个背靠背的数字交换了.
还有就是如何用栈来iterative inorder traversal.
最后就是不要用Stack类而是Deque类, new一个ArrayDeque. 因为后者提供了更全面的功能. Queue用Deque也挺好.
时间复杂度: O(n)
空间复杂度: O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { private TreeNode lastVisited = null, x = null, y = null;
public void recoverTree(TreeNode root) { Deque<TreeNode> stack = new ArrayDeque<>(); while (!stack.isEmpty() || root != null) { while (root != null) { stack.push(root); root = root.left; } TreeNode currNode = stack.pop(); if (lastVisited != null && currNode.val < lastVisited.val) { y = currNode; if (x == null) { x = lastVisited; } else { break; } } lastVisited = currNode; root = currNode.right; } swap(x, y); }
private void swap(TreeNode nodeOne, TreeNode nodeTwo) { int temp = nodeOne.val; nodeOne.val = nodeTwo.val; nodeTwo.val = temp; } }
|
Iterative 版本, 其实就是模仿栈的工作, 先疯狂压左边, 等到左边是null的时候, pop出来一个, 然后在走右边一个node, 同样疯狂压右边node的左边.
时间复杂度和空间复杂度不变.