天天看點

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

以下為我的天梯積分規則:

每日至少一題:一題積分+10分

若多做了一題(或多一種方法解答),則當日積分+20分(+10+10)

若做了三道以上,則從第三題開始算+20分(如:做了三道題則積分-10+10+20=40;做了四道題則積分–10+10+20+20=60)

初始分為100分

若差一天沒做題,則扣積分-10分(周六、周日除外注:休息)

堅持!!!

初級算法

刷題目錄

連結清單

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

題幹

給你一個

二叉樹

的根節點 root ,判斷其是否是一個有效的

二叉搜尋樹

有效 二叉搜尋樹定義如下:

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

示例 1:

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

輸入:root = [2,1,3]

輸出:true

示例2:

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

輸入:root = [5,1,4,null,null,3,6]

輸出:false

解釋:根節點的值是 5 ,但是右子節點的值是 4 。

提示:

樹中節點數目範圍在[1, 10^4] 内

-2^31 <= Node.val <= 2^31 - 1

中序周遊

分析:

可能由讀者不知道中序周遊是什麼,我們這裡簡單提及一下,中序周遊是二叉樹的一種周遊方式,它先周遊左子樹,再周遊根節點,最後周遊右子樹。而我們二叉搜尋樹保證了左子樹的節點的值均小于根節點的值,根節點的值均小于右子樹的值,是以中序周遊以後得到的序列一定是升序序列。(引用自了力扣原始解釋,這個解釋很通透!)

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹
class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        if not root:
            return True
        
        prev = None 
        stack = []
        while stack or root:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            # 若中序周遊得到的節點的值小于前一個值prev,那麼就說明不是二叉搜尋樹,傳回False
            if prev and root.val <= prev.val:
                return False
                # 儲存上一節點
            prev = root
            root = root.right
        return True      

這個速度超級快,超過100%!!!

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

思路很不錯!!!多多練習

搜尋(遞歸)

有大佬分析的很透徹,來看下面的圖

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

注意6這個節點不光要小于15而且還要大于10,是以這裡的每一個節點都是有一個範圍的。這裡我們來給每個節點添加一個範圍,如果不在這個範圍之内直接傳回false,比如6的範圍是(10,15),很明顯他不在這個範圍内,是以他不是

。下面方法可能不完全按照上面解釋一緻。

class Solution:
    prev = None  # 用于記錄前一個節點
    def isValidBST(self, root: TreeNode) -> bool:
        if not root:
            return True
        # 從左開始遞歸
        if not self.isValidBST(root.left):
            return False
        # 判斷前一節點是否大于目前
        if self.prev is not None and self.prev.val >= root.val:
            return False

        # 儲存前個節點
        self.prev = root

        # 右邊遞歸
        if not self.isValidBST(root.right):
            return False
        return True      
<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹

增加上下界的寫法:

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
    # 遞歸并引入上界,下界來判斷是否有效的二叉搜尋樹
        def chesh(node, min_val = float('-inf'), max_val = float('inf')) -> bool:
            if not node:
                return True
            #每個節點如果超過這個範圍,直接傳回false,設定出口
            if node.val <= min_val or node.val >= max_val:
                return False
            #這裡再分别以左右兩個子節點分别判斷
            #左子樹範圍的最小值是minVal,最大值是目前節點的值,也就是root的值,因為左子樹的值要比目前節點小       
            #右子數範圍的最大值是maxVal,最小值是目前節點的值,也就是root的值,因為右子樹的值要比目前節點大
            return chesh(node.left, min_val, node.val) and chesh(node.right, node.val, max_val)
        return chesh(root)      

複現大佬的Java代碼。

<LeetCode天梯>Day031 驗證二叉搜尋樹(遞歸+中序周遊) | 初級算法 | Python題幹