很巧妙的一题,http://yucoding.blogspot.com/2013/03/leetcode-question-75-recover-binary.html 解释的很详细。
tricky的地方在于要注意只有两个元素的情况
package Level4; import Utility.TreeNode; /** * Recover Binary Search Tree * * Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure. Note: A solution using O(n) space is pretty straight forward. Could you devise a constant space solution? confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. OJ's Binary Tree Serialization: The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below. Here's an example: 1 / \ 2 3 / 4 \ 5 The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}". * */ public class S99 { public static void main(String[] args) { } TreeNode pre; // 指向当前遍历元素的前一个 TreeNode first; // 第一个乱序的元素 TreeNode second;// 第二个乱序的元素 public void inorder(TreeNode root){ if(root == null){ return; } inorder(root.left); if(pre == null){ pre = root; }else{ if(pre.val > root.val){ if(first == null){ first = pre; // 找到第一个乱序的元素 } second = root; // 第二个乱序的元素。如果用了else,则无法通过只有两个元素的情况 } pre = root; // 继续搜索 } inorder(root.right); } public void recoverTree(TreeNode root) { pre = null; // 必须在这里初始化一遍,否则OJ会报错 first = null; second = null; inorder(root); if(first!=null && second!=null){ // 只需要交换元素值,而没必要进行指针操作! int tmp = first.val; first.val = second.val; second.val = tmp; } } }
具体的思路,还是通过中序遍历,只不过,不需要存储每个节点,只需要存一个前驱即可。
例如1,4,3,2,5,6
1.当我们读到4的时候,发现是正序的,不做处理
2.但是遇到3时,发现逆序,将4存为第一个错误节点,3存为第二个错误节点
3.继续往后,发现3,2又是逆序了,那么将第2个错误节点更新为2
如果是这样的序列:1,4,3,5,6同上,得到逆序的两个节点为4和3。
同理对于边界情况也是可以处理的,例如2,1
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { TreeNode first = null, second = null, pre = null; public void recoverTree(TreeNode root) { find(root); swap(first, second); } public void find(TreeNode root) { if(root == null) { return; } find(root.left); if(pre == null) { // initialize pre in the very beginning pre = root; } else{ if(pre.val > root.val){ // out of order if(first == null) { // first time first = pre; second = root; } else { // second time second = root; } } pre = root; // update pre to current node } find(root.right); } // swap binary tree node public void swap(TreeNode a, TreeNode b) { int tmp = a.val; a.val = b.val; b.val = tmp; } }