原题链接在这里:https://leetcode.com/problems/recover-binary-search-tree/
采用inorder遍历BST应该是返回从小到大的顺序,但这里有两个点顺序错了,所以不会完全从小到大。
如果两个相邻点顺序错了,inorder就应该有一个地方大小顺序颠倒,如果不是相邻点顺序错了,inorder应有两个地方大小顺序颠倒。
e.g. 1234567, 若果2和5调换,结果是1534267, 第一个大小顺序颠倒的“53”中的fist number和第二个大小顺序颠倒的“42”中的second number 调换回来即可。
若是用一个list表示inorder结果就轻松很多,但要求constant space.
用两个点来找到例子中的5 和 2,然后调换两个点即可。这里应用list是因为Java 是pass by value, 必须借用list这种object才行。
递归的过程就像inorder,pre 存储 刚才扫过的点,若是现在的点root比pre的val小就找到了大小顺序颠倒。
先存当前颠倒的两个数到res里,如果后面又有颠倒,则把第二个颠倒里的两个数中的后一个更新到res的第二个点。如此res就包含了要对调的两个点。
AC Java:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public void recoverTree(TreeNode root) {
List<TreeNode> pre = new ArrayList<TreeNode>();
pre.add(null);
List<TreeNode> res = new ArrayList<TreeNode>();
findNode(root,pre,res);
swapNode(res.get(0),res.get(1));
}
private void findNode(TreeNode root, List<TreeNode> pre, List<TreeNode> res){
if(root == null){
return;
}
findNode(root.left,pre,res);
if(pre.get(0) != null && root.val < pre.get(0).val){
if(res.size() == 0){
res.add(pre.get(0));
res.add(root);
}
res.set(1,root);
}
pre.set(0,root);
findNode(root.right,pre,res);
}
private void swapNode(TreeNode tn1, TreeNode tn2){
int temp = tn1.val;
tn1.val = tn2.val;
tn2.val = temp;
}
}