LeetCode99. 恢复二叉搜索树
题目描述
/**
*
* 给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。
* 请在不改变其结构的情况下,恢复这棵树。
* <p>
* 进阶:使用 O(n) 空间复杂度的解法很容易实现。
* 你能想出一个只使用常数空间的解决方案吗?
*
*/
思路分析
- 先对二叉搜索树进行中序遍历,将每个节点的值存储到集合中
- 如果节点没有被交换,正常情况下,通过中序遍历后的二叉搜索树的节点值是升序排列的
- 当有节点发生交换时,得到的序列会出现逆序的情况,因此可以通过逆序判断哪两个节点被交换,将节点对应的值记录在数组中
- 再次遍历二叉搜索树,找到被交换的节点的值 ,并交换
- 源码及分析见下
源码及分析
public void recoverTree(TreeNode root) {
//定义集合保存中序遍历的结果
List<Integer> list = new ArrayList<>();
inorder(root, list);
int[] swapped = findTwoSwapped(list);
recover(root, 2, swapped[0], swapped[1]);
}
/**
* 使用中序遍历将二叉树各个节点的值保存在集合中
*
* @param root 根节点
* @param list 保存二叉树节点的值
*/
public void inorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
//向左递归
inorder(root.left, list);
list.add(root.val);
//向右递归
inorder(root.right, list);
}
/**
* @param list 二叉树的元素
* @return 返回找到的数字
*/
public int[] findTwoSwapped(List<Integer> list) {
//定义变量记录要交换的值
int x = -1, y = -1;
//遍历集合寻找逆序的树
for (int i = 0; i < list.size() - 1; i++) {
//如果发现有逆序的数,则记录
if (list.get(i) > list.get(i + 1)) {
y = list.get(i + 1);
if (x == -1) {
x = list.get(i);
} else {
break;
}
}
}
return new int[]{x, y};
}
/**
* 通过递归将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) {
//递归时如果发现当前节点的值是x 或者y
if (root.val == x || root.val == y) {
root.val = root.val == x ? y : x;
//递归结束条件,即交换两次后结束
if (--count == 0) {
return;
}
}
//向右递归查找并交换
recover(root.right, count, x, y);
//向左递归查找并交换
recover(root.left, count, x, y);
}
}