leetcode 99: 恢复二叉搜索树
给你二叉搜索树的根节点 root
,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
示例 1:
输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
示例 2:
输入:root = [3,1,4,null,null,2]
输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
提示:
- 树上节点的数目在范围
[2, 1000]
内 -231 <= Node.val <= 231 - 1
**进阶:**使用 O(n)
空间复杂度的解法很容易实现。你能想出一个只使用 O(1)
空间的解决方案吗?
Related Topics
树
深度优先搜索
二叉搜索树
二叉树
思路:
- 把二叉搜索树中的元素中序遍历到一个集合中。
- 然后找到顺序不符合的地方。有2种可能性
- 调换顺序的2个元素相邻,ai>ai+1,只需要交换ai和ai+1
- 调换顺序的2个元素不相邻,那么会造成ai>ai+1、aj>aj+1,我们只需要调换ai和aj+1
- 根据遍历的集合找到需要调换的2个元素
- 然后中序遍历找到这2个元素进行调换。
class Solution {
public void recoverTree(TreeNode root) {
//遍历二叉搜索树 拿到结果
List<Integer> list = new ArrayList<>();
inOrder(root,list);
//找到需要交换的2个数
int[] nums = findTwoSwap(list);
//交换
recovery(root,2,nums[0],nums[1]);
}
public void inOrder(TreeNode root,List<Integer> list){
if(root == null){
return;
}
inOrder(root.left,list);
list.add(root.val);
inOrder(root.right,list);
}
//找到需要交换的2个元素
//2种情况: 1. 被交换的2个元素相邻 ai > ai+1 只需要交换ai和ai+1
// 2. 不相邻 会出现2次 ai > ai+1 aj > aj+1 那么只需要交换ai和aj+1
public int[] findTwoSwap(List<Integer> list){
int x,y;
x = y = -1;
for(int i = 1 ; i < list.size();i++){
if(list.get(i) < list.get(i-1)){
y = i;
if(x == -1){
x = i-1;
}else{
break;
}
}
}
return new int[]{list.get(x),list.get(y)};
}
//交换x和y的值 如果交换完毕 可以直接退出循环
public void recovery(TreeNode root,int count ,int x, int y){
if(root == null){
return;
}
//如果是x 就交换成y 是y变成x
if(root.val == x || root.val == y){
root.val = root.val == x ? y : x;
count--;
if(count == 0){
return;
}
}
recovery(root.left,count,x,y);
recovery(root.right,count,x,y);
}
}