leetcode 99 恢复二叉搜索树
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
第一种解法
题目要求的是二叉搜索树,二叉搜索树有一个特点,那就是有序,所以我们可以得知在中序遍历二叉搜索树得到的序列是递增的。
现在题目给出有两个节点被错误的交换了,那在中序遍历的序列中就可以体现出来了,那就是里面有数据是非递增的,也就是存在nums[i] > nums[i+1],如果是相邻的两个节点被交换了,那就只有一个位置进行了交换,如果不是那就存在两个位置的进行了交换。即nums[i] > nums[i+1]或nums[i] > nums[i+1] 和 nums[j] > nums[j+1]。
由此可以确定解题思路:
- 通过中序遍历得到一组序列
- 在这个序列中找到哪两个节点进行了交换
- 将两个节点的数据交换回来
代码如下:
public void recoverTree(TreeNode root) {
List<Integer> nums = new ArrayList<Integer>();
// 1、先遍历树,通过中序遍历,二叉搜索树在中序遍历的情况下为递增序列
inorder(root, nums);
// 2、查看树的哪连个节点交换了位置
int[] swapped = findTwoSwapped(nums);
// 3、将两个节点的数据交换回来
recover(root, 2, swapped[0], swapped[1]);
}
/**
* 中序遍历
*
* @param root
* @param nums
*/
public void inorder(TreeNode root, List<Integer> nums) {
if (root == null) {
return;
}
inorder(root.left, nums);
nums.add(root.val);
inorder(root.right, nums);
}
/**
* 找到交换了数据的位置
*
* @param nums
* @return
*/
public int[] findTwoSwapped(List<Integer> nums) {
int x = -1, y = -1;
for (int i = 0; i < nums.size() - 1; i++) {
if (nums.get(i + 1) < nums.get(i)) {// 如果后面的数小于前面的数,说明这里被交换过
// 不满足位置交换的点有一个或两个
// 如果有一个,那就是i和i+1是交换点
// 如果有两个,那就是 i 和 j+1
// 使用x表示下标为i的值,使用y表示下标为i+1的值
y = nums.get(i + 1);
if (x == -1) {
x = nums.get(i);
} else {
break;
}
}
}
return new int[]{x, y};
}
/**
* 还原二叉搜索树
* @param root
* @param count 交换的次数
* @param x 交换的节点1
* @param y 交换的节点2
*/
public void recover(TreeNode root,int count,int x,int y){
if (root != null){
if (root.val == x || root.val == y){
root.val = root.val == x ? y : x;// 如果这个节点的值为x,那么原数据值为y,反之亦然
if (--count == 0){
return;
}
}
recover(root.left,count,x,y);
recover(root.right, count, x, y);
}
}
时间复杂度为:O(N),N为二叉树的节点
空间复杂度为:O(N)
第二种解法:
第一种方法使用了额外的数组来存储中序遍历得到的序列,所以空间复杂度为O(N),可以不需要额外的空间进行存储序列,也能找到两个交换的节点,那就是在中序遍历的时候进行判断,判断后面的节点是否小于当前节点。
使用迭代进行中序遍历:
代码如下:
public void recoverTree(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode x = null;
TreeNode y = null;
TreeNode pre = null;
while (!stack.isEmpty() || root != null){
while (root != null){
stack.push(root);
root = root.left;
}
root = stack.pop();
if (pre != null && pre.val > root.val){
y = root;
if (x == null){
x = pre;
}else {
break;
}
}
pre = root;
root = root.right;
}
swap(x,y);
}
/**
* 交换函数
* @param x
* @param y
*/
public void swap(TreeNode x,TreeNode y){
int temp = x.val;
x.val = y.val;
y.val = temp;
}
刷了一些leetcode,然后来写一些博客,加深自己解题的思路。