1. 程式人生 > >Leetcode 98:驗證二叉搜尋樹(最詳細的解法!!!)

Leetcode 98:驗證二叉搜尋樹(最詳細的解法!!!)

給定一個二叉樹,判斷其是否是一個有效的二叉搜尋樹。

假設一個二叉搜尋樹具有如下特徵:

  • 節點的左子樹只包含小於當前節點的數。
  • 節點的右子樹只包含大於當前節點的數。
  • 所有左子樹和右子樹自身必須也是二叉搜尋樹。

示例 1:

輸入:
    2
   / \
  1   3
輸出: true

示例 2:

輸入:
    5
   / \
  1   4
     / \
    3   6
輸出: false
解釋: 輸入為: [5,1,4,null,null,3,6]。
     根節點的值為 5 ,但是其右子節點值為 4

解題思路

這個問題和之前的問題Leetcode 110:平衡二叉樹(最詳細的解法!!!)

類似,但是這個問題有一個陷阱,我們參考之前的寫法,很容易寫出下面這種寫法。

class Solution:
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True

        if root.left and root.left.val >= root.val:
            return False

        if
root.right and root.right.val <= root.val: return False return self.isValidBST(root.left) and self.isValidBST(root.right)

上述寫法,沒有考慮這種情況

    10
   /  \
  5    15
      /  \
     6    20

這種寫法的錯誤在於沒有理清楚子問題的本質。節點左子樹的所有節點都小於當前節點,而不是僅僅左根節點小於root,對於右子樹同理。我們只要對上述寫法稍加修改

class Solution
:
def _isValidBST(self, root, min_t=float('-inf'), max_t=float('inf')): if not root: return True if min_t < root.val < max_t and self._isValidBST(root.left, min_t, root.val) and self._isValidBST(root.right, root.val, max_t): return True return False def isValidBST(self, root): """ :type root: TreeNode :rtype: bool """ return self._isValidBST(root)

這裡我更加推薦下面的這種寫法

class Solution:
    def _isValidBST(self, root, left=None, right=None):
        if not root:
            return True

        if left and left.val >= root.val:
            return False

        if right and right.val <= root.val:
            return False

        return self._isValidBST(root.left, left, root) and self._isValidBST(root.right, root, right)

    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self._isValidBST(root)

我們同樣寫出遞迴版本,我們這裡要用到一個很重要的性質。

二分搜尋樹的中序遍歷是一個有序數列

所以我們這裡可以使用中序遍歷的遞迴寫法解決這個問題。

class Solution:
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True

        pre = None
        stack = list()
        while root or stack:
            if root:
                stack.append(root)
                root = root.left
            else:
                root = stack.pop()
                if pre and root.val <= pre.val:
                        return False

                pre = root
                root = root.right

        return True

如有問題,希望大家指出!!!