Version: Next

99.恢复二叉搜索树

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:

img

输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。

示例 2:

img

输入: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个逆序对:第一个逆序对的左 和 第二个逆序对的右 交换
    • 合并两种情况:不论一个还是两个逆序对,都是找逆序对的
正确111718222837424462
交换相邻的 2228
产生一个逆序对
111718282237424462
交换不相邻的 1844
产生两个逆序对
111744222837421862

实现:

  • 中序遍历二叉搜索树,每个节点都与上一个节点的值进行比较
  • 如果找到逆序对,将逆序对的 记录为错误节点1, 记录为错误节点2
    • 如果只出现一次逆序对:直接得到了正确头尾
    • 如果出现两次逆序对:头就是第一次逆序对中的头,即错误节点1;尾要更新为第二个逆序对的尾
    • 综上:只有错误节点1为 null 时才记录错误节点1,而错误节点2总是更新
  • 时间复杂度:O(n)
  • 空间复杂度:O(树高) = O(h) ,最坏情况下,树退化为链表,则空间复杂度为 O(n),最好为 O(logn)

Morris中序遍历|空间复杂度O(1)