二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 1:
输入: [1,3,null,null,2]
1
/
3
2
输出: [3,1,null,null,2]
3
/
1
2
示例 2:
输入: [3,1,4,null,null,2]
3
/
1 4
/
2
输出: [2,1,4,null,null,3]
2
/
1 4
/
3
进阶:
使用 O(n) 空间复杂度的解法很容易实现。
你能想出一个只使用常数空间的解决方案吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/recover-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二叉搜索树往往与树的中序遍历有关。
将树做中序遍历后得到遍历结果,对遍历结果进行查找,找到一个或两个逆序对,如果只有一个逆序对,那么将逆序元素交换;如果有两个逆序对,将第一个逆序对的前元素和第二个元素的后元素交换,就可以得到正常遍历结果,也就是说数还原成了二叉搜索树。
因此,首先对数中序遍历,其次将逆序对按照上面的规则找出来,再遍历树将逆序对的值交换即可。
下面的解法是首先将中序遍历结果拿到,然后找到逆序对,这一操作也可以直接在中序遍历时拿到逆序对,然后接下来的遍历树交换节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public void recoverTree(TreeNode root) {
if(root == null)
return;
List<Integer> list = new ArrayList<>();
getInOrder(root,list);
int[] descPair = findDescPair(list);
exchange(root,descPair);
}
private void getInOrder(TreeNode root,List<Integer> list) {
if(root == null)
return;
getInOrder(root.left,list);
list.add(root.val);
getInOrder(root.right,list);
}
private int[] findDescPair(List<Integer> list) {
int[] res = new int[2];
int flag = 0;//0表示第一对,1表示第二对
for(int i = 1;i < list.size();i++) {
if(list.get(i-1) > list.get(i)) {
if(flag == 0) {
res[0] = list.get(i-1);
res[1] = list.get(i);
flag = 1;
}else {
res[1] = list.get(i);
break;
}
}
}
return res;
}
private void exchange(TreeNode root,int[] descPair) {
if(root == null)
return;
if(root.val == descPair[0] || root.val == descPair[1])
root.val = root.val == descPair[0] ? descPair[1] : descPair[0];
exchange(root.left,descPair);
exchange(root.right,descPair);
}
}