Leetcode 99:恢复二叉搜索树(超详细的解法!!!)

二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

示例 1:

输入: [1,3,null,null,2]

   1
  /
 3
  \
   2

输出: [3,1,null,null,2]

   3
  /
 1
  \
   2

示例 2:

输入: [3,1,4,null,null,2]

  3
 / \
1   4
   /
  2

输出: [2,1,4,null,null,3]

  2
 / \
1   4
   /
  3

进阶:

  • 使用 O(n) 空间复杂度的解法很容易实现。
  • 你能想出一个只使用常数空间的解决方案吗?

解题思路

这个问题非常简单。我们知道二分搜索树的中序遍历是一个单调递增的数组。对于例一来说,输入树的中序遍历是

3 2 1

很明显,此时不是递增数组,我们只需要将31换一下位置即可。对于例二来说,输入树的中序遍历是

1 3 2 4

此时也不是递增数组,我们只需要将23换一下位置即可。现在的问题是我们怎么知道要交换哪两个数呢?我们可以对输入的树进行中序遍历,遍历的过程中判断之前访问的节点pre.val是不是大于当前访问的节点cur.val,如果是的话,我们就要记录pre,此时pre就是要交换的第一个元素。然后我们继续遍历,直到再也没有出现pre.val > cur.val的情况了,此时我们最后一次出现的cur就是我们要交换的第二个元素(参考第一个例子)。关于遍历操作,可以参看如下这几篇

Leetcode 144:二叉树的前序遍历(最优雅的解法!!!)

Leetcode 94:二叉树的中序遍历(最优雅的解法!!!)

Leetcode 145:二叉树的后序遍历(最详细的解法!!!

class Solution:
    def recoverTree(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        self.pre = None
        self.m1, self.m2 = None, None
        self.inorderTraversal(root)
        self.m1.val, self.m2.val = self.m2.val, self.m1.val
        
    def inorderTraversal(self, root):
        if root:
            self.inorderTraversal(root.left)
            if self.pre != None and self.pre.val > root.val:
                if self.m1 == None:
                    self.m1 = self.pre
                self.m2 = root
            self.pre = root
            self.inorderTraversal(root.right)

同时我们也可以轻松的写出迭代版本。

class Solution:
    def recoverTree(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        cur, pre = root, None
        first, second = None, None
        stack = []
        
        while cur or stack:
            if cur:
                stack.append(cur)
                cur = cur.left
            else:        
                node = stack.pop()
                if pre and pre.val >= node.val:
                    if not first:
                        first = pre
                    second = node
                    
                pre = node
                cur = node.right
        
        first.val, second.val = second.val, first.val

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页