1. 程式人生 > >LeetCode Medium 98 驗證二叉搜尋樹 Python

LeetCode Medium 98 驗證二叉搜尋樹 Python

def isValidBST(self, root):
    """
    My Method 2
    Solution Method 也是這個思路
    演算法:遞迴
    思路:
        在遞迴的過程中判斷左右是否滿足要求
        遞迴的時候用min_border和 max_border記錄當前位置最小不能小於多少,最大不能大於多少
        左側節點應該小於當前根節點,但是不能小於min_border,比如下面的這個3,3小於4,但是3不應該小於5
        同理,右側節點的值應該大於當前根節點,但是不能大於最大的max_border
                5
               / \
              1   4
                 / \
                3   6
        往左子樹傳的時候,更新最大上界為root.val,最小上界不變,往右子樹傳的時候更新最小上界為root.val,最大上界不變
            所以向下傳的時候,向左側傳的話,就會更新max_border為root.val 左子樹中的值再小也不能小於min_border
        同理,向右子樹傳的時候,更新min_border 為root.val,右子樹中的值再大也不能大於max_border,二者是交替的,
        然後更新min的時候max保持不變
        3是4的左子樹,3小於4,但是再小也不能小於5,min_border是上一層的root.val = 5

        在最一開始的時候,上下界是沒關係的,可以認為是正負無窮,所以傳inf
    複雜度:
        時間:OK,第K個節點是不滿足條件的話,停止
        空間:OK,遞迴棧空間
    """

    def check_valid(root, min_border, max_border):
        if root == None:
            return True
        if root.left == None and root.right == None:
            return True
        left_check = right_check = True
        if root.left != None:
            if root.left.val >= root.val or root.left.val <= min_border:
                return False
            else:
                left_check = check_valid(root.left, min_border, root.val)
        if root.right != None:
            if root.right.val <= root.val or root.right.val >= max_border:
                return False
            else:
                right_check = check_valid(root.right, root.val, max_border)
        return left_check and right_check

    return check_valid(root, float('-inf'), float('inf'))


def isValidBST_bfs(self, root):
    """
    Solution Method 2
    將 DFS轉為BFS,用佇列按層遍歷,剩下的思路和上面是一樣的
        用棧也行,只不過用棧的話先壓右子樹再壓左子樹,這樣訪問的時候就是左右了
    訪問當前節點為root構成的子樹時。要確認root,root.left.val,root.right.val的值的狀態,每個root
    處都有一個lower_limit和upper_limit,所以用佇列/棧按層訪問也是一樣的,畢竟相當於是判斷一個區域性狀態
    """
    if not root:
        return True

    queue = [(root, None, None), ]
    while queue:
        root, lower_limit, upper_limit = queue.pop(0)
        if root.left:
            if root.left.val < root.val:
                if lower_limit and root.left.val <= lower_limit:
                    return False
                queue.append((root.left, lower_limit, root.val))
            else:
                return False
        if root.right:
            if root.right.val > root.val:
                if upper_limit and root.right.val >= upper_limit:
                    return False
                queue.append((root.right, root.val, upper_limit))
            else:
                return False
    return True
def isValidBST1(self, root):
    """
    My Naive Method
    演算法:遍歷
    思路:
        很樸素的思路,利用二叉搜尋樹的特性,中序遍歷得到的序列一定是有序序列,所以我就中序遍歷一次,得到
        值的列表result
        然後再遍歷result檢查,如果result不是有序陣列的話,就說明Tree一定不是一顆二叉搜尋樹
        其實效率還可以,遍歷一次所有的節點ON,然後檢查陣列也是ON,總體的時間是ON
    複雜度分析:
        時間:ON
        空間:ON
    """
    result = []

    def inorder(root):
        if root == None:
            return
        inorder(root.left)
        result.append(root.val)
        inorder(root.right)

    inorder(root)
    if len(result) in (0, 1):
        return True
    for i in range(1, len(result)):
        if result[i] <= result[i - 1]:
            return False
    return True