LeetCode第[98]題(Java):Validate Binary Search Tree(驗證二叉搜索樹)


題目:驗證二叉搜索樹

難度:Medium

題目內容

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.

翻譯

給定一棵二叉樹,確定它是否是一個有效的二叉搜索樹(BST)。

BST的定義如下:

節點的左子樹只包含小於節點鍵的鍵節點。

節點的右子樹只包含大於節點鍵的鍵節點。

左和右子樹都必須是二叉搜索樹。

Example 1:

Input:
    2
   / \
  1   3
Output: true

Example 2:

    5
   / \
  1   4
     / \
    3   6
Output: false

 

我的思路:搜索二叉樹的驗證就是要求每一個子樹都是滿足搜索樹的“左小右大”的規定,

1、先判斷自己作為根節點的左右二叉是否符合;

2、然后返回左右節點的遞歸結果的 “與” (全都符合才算符合)

 

我的代碼

 1     public boolean isValidBST(TreeNode root) {
 2         if (root == null) {
 3             return true;
 4         }
 5         
 6         if (root.left != null) {
 7             TreeNode cur = root.left;
 8             while (cur.right != null) {
 9                 cur = cur.right;
10             }
11             if (cur.val >= root.val) {
12                 return false;
13             }
14         }
15         
16         if (root.right != null) {
17             TreeNode cur = root.right;
18             while (cur.left != null) {
19                 cur = cur.left;
20             }
21             if (cur.val <= root.val) {
22                 return false;
23             }
24         }
25         
26         return isValidBST(root.left) && isValidBST(root.right);
27     }

我的復雜度:O(N*logN)

編碼過程中的問題

1、沒仔細看題,而且記錯搜索樹的定義了,當出現兩個值相等的時候,此時不是搜索樹

2、最開始只考慮到判斷根節點和左右兩個子節點就行了,結果后面案例跑錯了,例如:

    5
   / \
  1   6
     / \
    3   7    每個子樹都是正確的二叉搜索樹,但是整體上看,5的右子樹內有比它小的3,所以此樹不是二叉搜索樹。

 此時想到二叉樹刪除算法,當刪除節點有兩個子節點的時候,此時會選擇此節點左節點的最右子系節點,或者右節點的最左子系節點進行代替,所以這兩個節點值才是最接近根節點值的節點,所以每次的單個子樹判斷應該判斷這兩個,而不是左右子節點就行了。

 

答案代碼

1     public boolean isValidBST(TreeNode root) {
2         return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
3     }
4     
5     public boolean isValidBST(TreeNode root, long minVal, long maxVal) {
6         if (root == null) return true;
7         if (root.val >= maxVal || root.val <= minVal) return false;
8         return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);
9     }

答案復雜度:O(N)

答案思路

也是利用了遞歸的思想,分別對每一個子樹進行判斷,但是它的亮點在於在判斷的時候並不需要對子樹進行搜索“最相近的值”,而是利用了“最大值”、“最小值”的思想:

對於每個子樹,都有一個最大值和一個最小值

對於左子樹,最大值就是它的根節點的值,最小值是根節點的最小值(左父親或者MIN_VALUE)

對於右子樹,最小值就是它的根節點的值,最大值是根節點的最大值(右父親或者MAX_VALUE)

例如:

   5
   / \
  1   6
     / \
    3   7    
5的滿足小於最大值,大於最小值,然后遞歸(1,MIN,5) && 遞歸(4,5,MAX)
。。。
3節點的最大值為6,最小值應該為5,此時不滿足,所以return false

其實還有一種非遞歸的解法:中序遍歷,利用二叉搜索樹中序遍歷的有序性(在中序遍歷的出棧時判斷此值是否小於之前出棧的那個節點的值
 1 public boolean isValidBST(TreeNode root) {
 2    if (root == null) return true;
 3    Stack<TreeNode> stack = new Stack<>();
 4    TreeNode pre = null;
 5    while (root != null || !stack.isEmpty()) {
 6       while (root != null) {
 7          stack.push(root);
 8          root = root.left;
 9       }
10       root = stack.pop();
11       if(pre != null && root.val <= pre.val) return false;
12       pre = root;
13       root = root.right;
14    }
15    return true;
16 }

注意:不能使用出棧值與棧頂進行比較,因為在中序遍歷的過程中棧頂可能為空,所以此時無法比較。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM