LeetCode: 99. Recover Binary Search Tree

题目

原题地址:https://leetcode.com/problems/recover-binary-search-tree/

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Example 1:

Input: [1,3,null,null,2]

   1
  /
 3
  \
   2

Output: [3,1,null,null,2]

   3
  /
 1
  \
   2

Example 2:

Input: [3,1,4,null,null,2]

  3
 / \
1   4
   /
  2

Output: [2,1,4,null,null,3]

  2
 / \
1   4
   /
  3

Follow up:

  • A solution using O(n) space is pretty straight forward.
  • Could you devise a constant space solution?

解法

中序遍历找到值有误的两个节点,然后交换它们的值

通过 BST 的特性可以知道,中序遍历 BST 的过程类似于按节点值从小到大进行遍历的过程,因此我们可以在中序遍历的过程中找到这两个有误的节点,即导致遍历过程的节点的值不是有序的节点:

  • 因为是值交换了,所以,小值变成大值的元素的值会比它的下一个元素的值大,大值变成小值的元素的值会比它的上一个元素的值小(比如: [1, 3, 2, 4][3, 2, 1][6, 2, 3, 4, 1] )。
  • 因此,如果当前元素的值比它的下一个元素的值大的话,它就是第一个有误的节点。
  • 如果当前元素的值比它的上一个元素的值小的话,它就是另一个有误的节点。

找到有误的两个节点后,交换这两个节点值就可以了。

中序遍历的 Python 代码类似这样:

def inorder(root):
    if root is None:
        return
    inorder(root.left)

    # print(root)

    inorder(root.right)

这个方法的 Python 代码类似下面这样:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def recoverTree(self, root):
        self.pre = None
        self.first = None
        self.second = None

        self.inorder(root)

        self.first.val, self.second.val = self.second.val, self.first.val

        return root

    def inorder(self, root):
        if root is None:
            return

        self.inorder(root.left)

        if self.pre is not None and self.pre.val > root.val:
            if self.first is None:
                self.first = self.pre
            self.second = root

        self.pre = root

        self.inorder(root.right)

为什么 self.second = root 那里不加个 if self.second is None 的条件是为了支持 这两个元素是相邻元素(比如: [1, 3, 2, 4] )或非相邻元素(比如: [3, 2, 1] )这两种情况。


Comments