恢复二叉搜索树
难度:
标签:
题目描述
给你二叉搜索树的根节点 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)
空间的解决方案吗?
代码结果
运行时间: 68 ms, 内存: 15.3 MB
/*
题目思路:
通过中序遍历找到所有节点值,然后排序找到交换前后的正确顺序,最后再遍历一遍树来修复错误的值。
利用Java Stream将树的节点转换为流来处理。
*/
import java.util.*;
public class Solution {
public void recoverTree(TreeNode root) {
List<Integer> values = new ArrayList<>();
inorder(root, values);
List<Integer> sortedValues = values.stream().sorted().collect(Collectors.toList());
recover(root, new int[]{0}, sortedValues);
}
private void inorder(TreeNode root, List<Integer> values) {
if (root == null) return;
inorder(root.left, values);
values.add(root.val);
inorder(root.right, values);
}
private void recover(TreeNode root, int[] index, List<Integer> sortedValues) {
if (root == null) return;
recover(root.left, index, sortedValues);
root.val = sortedValues.get(index[0]++);
recover(root.right, index, sortedValues);
}
}
解释
方法:
这个题解使用中序遍历的方法来恢复二叉搜索树。在中序遍历二叉搜索树时,正常情况下节点值应该是递增的。如果出现节点值减小的情况,说明找到了被错误交换的两个节点。第一个错误节点是第一次发现节点值减小时的前一个节点,第二个错误节点是最后一次发现节点值减小时的当前节点。找到这两个节点后,交换它们的值即可恢复二叉搜索树。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在中序遍历中,如何准确地识别出第一个和第二个错误节点?请详细解释这两个节点的确定逻辑。
▷🦆
为什么可以确定只交换这两个节点的值就能恢复整个二叉搜索树的正确性?
▷🦆
题解中提到在最坏的情况下,二叉搜索树可能退化为一条链。在这种情况下,递归方法的效率如何?是否有更优的方法来处理这种极端情况?
▷🦆
如果在中序遍历过程中只发现一次逆序,请问这种情况下如何处理?是否也是交换这一次逆序中涉及的两个节点的值?
▷