Version: Next
99.恢复二叉搜索树
难度 困难
给你二叉搜索树的根节点 root
,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
You are given the root of a binary search tree (BST), where exactly two nodes of the tree were swapped by mistake. Recover the tree without changing its structure.
Follow up: A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
示例 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)
重要结论
对于二叉搜索树,其中序遍历结果是一个单调(递增、递减)序列
- 找中序遍历
逆序对
,两个倒错的节点,可能引发 1 个 或 2 个逆序对
- 错误交换两个挨在一起、连续的元素(数值上紧挨):会产生
1
个逆序对- 错误交换两个没有挨在一起,彼此之间有距离(数值上,两数之间还有其他元素):会产生
2
个逆序对- 找到逆序对进行交换
- 只有1个逆序对:他们俩交换
- 2个逆序对:第一个逆序对的左 和 第二个逆序对的右 交换
- 合并两种情况:不论一个还是两个逆序对,都是找逆序对的
头
和尾
正确 11 17 18 22 28 37 42 44 62 交换相邻的 22
、28
产生一个逆序对11 17 18 28
22
37 42 44 62 交换不相邻的 18
、44
产生两个逆序对11 17 44
22 28 37 42 18
62
实现:
- 中序遍历二叉搜索树,每个节点都与上一个节点的值进行比较
- 如果找到逆序对,将逆序对的
头
记录为错误节点1,尾
记录为错误节点2
- 如果只出现一次逆序对:直接得到了正确头尾
- 如果出现两次逆序对:头就是第一次逆序对中的头,即错误节点1;尾要更新为第二个逆序对的尾
- 综上:只有错误节点1为 null 时才记录错误节点1,而错误节点2总是更新
- 时间复杂度:O(n)
- 空间复杂度:O(树高) = O(h) ,最坏情况下,树退化为链表,则空间复杂度为 O(n),最好为 O(logn)