LeetCode98.驗證二叉搜尋樹
阿新 • • 發佈:2021-07-22
題目
給定一個二叉樹,判斷其是否是一個有效的二叉搜尋樹。
假設一個二叉搜尋樹具有如下特徵:
節點的左子樹只包含小於當前節點的數。
節點的右子樹只包含大於當前節點的數。
所有左子樹和右子樹自身必須也是二叉搜尋樹。
示例1:
輸入:
2
/ \
1 3
輸出: true
示例 2:
輸入:
5
/ \
1 4
/ \
3 6
輸出: false
解釋: 輸入為: [5,1,4,null,null,3,6]。
根節點的值為 5 ,但是其右子節點值為 4 。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/validate-binary-search-tree
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
解題思路
遞迴
如果該二叉樹的左子樹不為空,則左子樹上所有節點的值均小於它的根節點的值; 若它的右子樹不空,則右子樹上所有節點的值均大於它的根節點的值;它的左右子樹也為二叉搜尋樹。
時間複雜度 : O(n) 空間複雜度:O(n)
中序遍歷
二叉搜尋樹保證了左子樹的節點的值均小於根節點的值,根節點的值均小於右子樹的值,因此中序遍歷以後得到的序列一定是升序序列 時間複雜度 : O(n) 空間複雜度:O(n) 助解:假設現在有二叉樹 5 / \ 3 6 先遍歷所有左節點,全部放入棧中 stack = [5,3] 遍歷完所有左節點後 從棧中取出 3 stack = [5] 判斷是否小於 變數inorder 用於儲存中序節點val inorder初始化的值為min,所以不可能小 inorder賦值3 把節點root=root.right(nil) 繼續下一次迴圈 root=3的節點沒有右節點,所以跳過壓入棧迴圈 再次從棧中pop節點 5 stack = [] 判斷節點5(中節點)是否小於3(左節點),不小於說明符合有序二叉樹 inorder賦值5 把節點root=root.right(6) 繼續下一次迴圈 節點6不為空,壓入棧中 stack = [6] root = root.left 由於節點6沒有子節點了,進入下一步 把節點6從棧中取出 stack = [] 判斷節點6(右節點)是否小於5(中節點),不小於說名符合有序二叉樹 把節點root=root.right(nil) 繼續下一次迴圈 棧為空,root為nil,不滿足最外層迴圈條件,程式結束 返回true
程式碼
type TreeNode struct { Val int Left *TreeNode Right *TreeNode } // 遞迴 func isValidBST(root *TreeNode) bool{ return helper(root,math.MinInt64,math.MaxInt64) } func helper(root *TreeNode,lower,upper int) bool { // 遞迴到節點為空結束 if root == nil{ return true } // 左節點:如果左節點大於等於根節點 false // 右節點:如果右節點小於等於跟節點 false if root.Val <= lower || root.Val >= upper{ return false } // 遞迴左右節點 return helper(root.Left,lower,root.Val) && helper(root.Right,root.Val,upper) } // 中序遍歷 func isValidBST2(root *TreeNode) bool { // 棧儲存節點 stack := []*TreeNode{} inorder := math.MinInt64 // 當棧所有節點被取出 以及 節點為空時結束迴圈 for len(stack) > 0 || root != nil{ // 先把所有節點壓入棧 for root != nil{ stack = append(stack,root) root = root.Left } // pop棧,判斷是否符合有序二叉樹 root = stack[len(stack)-1] stack = stack[:len(stack)-1] if root.Val <= inorder{ return false } // 儲存根節點值,切換到右子樹 inorder = root.Val root = root.Right } return true }