思路很简单,因为只有两个节点互换了,只需要找到这两个节点,再换回来即可
可是怎么找到这两个节点呢?
方法一
直接中序遍历得到一个数组arr1,然后新建一个数组arr2,copy arr1,将其排序
对比arr1和arr2,很容易就能找到不同的两个节点,互换即可
时间复杂度为o(nlogn)
class Solution { public void recoverTree(TreeNode root) { List<Integer> sorted = new ArrayList<>(); inorder(root, sorted); List<Integer> tmp = new ArrayList<>(sorted); Collections.sort(tmp); int[] pair = new int[2]; int count = 0; for(int i=0; i<sorted.size(); i++){ if(sorted.get(i) != tmp.get(i)){ pair[count++] = sorted.get(i); } } dfs(root, pair); } private void inorder(TreeNode root, List<Integer> sorted){ if(root == null) return; inorder(root.left, sorted); sorted.add(root.val); inorder(root.right, sorted); } private void dfs(TreeNode root, int[] tmp){ if(root == null) return; if(root.val == tmp[0]){ root.val = tmp[1]; }else if(root.val == tmp[1]) root.val = tmp[0]; dfs(root.left, tmp); dfs(root.right, tmp); } }
方法二
只用一个中序遍历,first记录第一个错误节点,second同理
第一个出错的节点,肯定是他的值比后一个节点的值大
第二个出错的节点,肯定是它的值比前一个节点的值小
按照这个规律,就可以找到这两个出错的节点
class Solution { TreeNode first = null; TreeNode second = null; TreeNode prev = new TreeNode(Integer.MIN_VALUE); public void recoverTree(TreeNode root) { inorder(root); int tmp = first.val; first.val = second.val; second.val = tmp; } private void inorder(TreeNode root){ if(root == null) return; inorder(root.left); if(first == null && prev.val > root.val){ first = prev; } if(first != null && prev.val > root.val){ second = root; } prev = root; inorder(root.right); } }