LeetCode 98. Validate Binary Search Tree(判斷是否爲二叉搜索樹,C++,python)

98. Validate Binary Search Tree
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.

Example 1:

Input:

    2
   / \
  1   3

Output: true

Example 2:

    5
   / \
  1   4
     / \
    3   6

Output: false

Explanation: The input is: [5,1,4,null,null,3,6]. The root node’s value is 5 but its right child’s value is 4.

思路:二叉搜索樹就是左子樹中的節點比根節點小,右子樹中節點值比根節點大。看到和樹相關的題目很自然會想到遞歸的做法。根據二叉搜索樹的性質,可以遞歸地判斷當前節點作爲根節點其左孩子是否比根節點小,並且其右孩子是否比根節點大。 於是可以寫出如下的程序。

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.validBST(root)
    
    def validBST(self, root):
        if root == None:
            return True
        
        leftNode = root.left
        rightNode = root.right
        if leftNode and leftNode.val >= root.val:
            return False
        if rightNode and rightNode.val <= root.val:
            return False
        return self.validBST(leftNode) and self.validBST(rightNode)

但是你會看到:
在這裏插入圖片描述

這裏這個6雖然小於15,但是6比根節點10小。而二叉搜索樹的所有右子樹應該比根節點大。所以上面這種只判斷一個由3個節點構成的子樹是否符合二叉搜索樹的性質是不行的,只考慮了局部,沒有考察整體。
在這裏插入圖片描述
上面的思路行不通,我們必須換一個思路。其實從上面的比較中發現,二叉搜索樹其實可以看成一個節點的數值是否在某個區間內。所以我們轉換思路。首先根節點的範圍沒有限制,只要在正負無窮之間即可,而其左子樹應該比根節點的值小,所以左子樹屬於的區間應該小於根節點的值;右子樹應該比根節點的值大,所以右子樹屬於的區間應該大於根節點的值。 一個例子如下圖,可以看到節點6不屬於區間(10, 15),所以這棵樹不是二叉搜索樹。
在這裏插入圖片描述
上面思路的python實現:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.validBST(root, -float('inf'), float('inf'))
    
    def validBST(self, root, left, right):
        if root == None:
            return True
        leftNode = root.left
        rightNode = root.right
        rootVal = root.val
        if rootVal<=left or rootVal>=right:
            return False
        return self.validBST(leftNode, left, rootVal) and self.validBST(rightNode, rootVal, right)

結果:在這裏插入圖片描述

c++實現:
不得不提一下,如果你自己用c++嘗試了這題,應該會發現這題很多數據點設計的很巧妙,很多地方會涉及無窮大無窮小,一不小心容易造成溢出。python中可以用float('inf')表示無窮大,-float('inf')表示無窮小,而c++中並沒有絕對的無窮大,剛好這題節點的數值只是int類型,所以不能用INT_MAXINT_MIN,而換成INT64_MAXINT64_MIN即可。上面這種做法在數據能達到INT64_MAXINT64_MIN時就不行了。後面我自己寫了個重載運算符來間接實現無窮大無窮小,有些麻煩,不過能做出來,而且數據更大應該也沒問題。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    bool binaryTree = true;
    
    bool isValidBST(TreeNode* root) {
        validBST(root, INT64_MIN, INT64_MAX);//INT64_MIN, INT64_MAX
        return binaryTree;
    }
    
    void validBST(TreeNode* root, long left, long right){//long
        if(root == NULL)
            return;
        TreeNode* leftNode = root->left;
        TreeNode* rightNode = root->right;
        if(root->val<=left || root->val>=right)//看成開區間
        {
            binaryTree = false;
            return;
        }
        validBST(leftNode, left, root->val);//如果是int 不能減一root-val-1
        validBST(rightNode, root->val, right);//如果是int 不能加一root->val+1數據可能會溢出
    }
};

結果
在這裏插入圖片描述

另一個版本,有點複雜,但是適用性更強,上面的方法對這題已經OK。有興趣可以看看,個人能力有限,歡迎提出更簡單的方法。。。

class Myint{
public:
    Myint(int type, int val = 0){
        this->type = type;
        this->val = val;
    }
    bool operator<=(int val){
        if(type == 1)//無窮大
        {
            return false;//無窮大不比任何數小
        }
        else if(type == 0){
            return true;//無窮小比任何數小
        }
        else{
            return this->val<=val;//此時Myint表示一個普通整數
        }
    }
    bool operator<=(Myint myint){
        if(type == 1)//無窮大
        {
            return false;//無窮大不比任何數小
        }
        else if(type == 0){
            return true;
        }
        else{
            return this->val<=myint.getVal();
        }
    }
    bool operator>=(int val){
        if(type == 1){
            return true;//無窮大比任何數大
        }
        else if(type == 0){
            return false;//無窮小比任何數小
        }
        else{
            return this->val>=val;
        }
    }
    
    bool operator>=(Myint myint){
        if(type == 1){
            return true;//無窮大比任何數大
        }
        else if(type == 0){
            return false;//無窮小比任何數小
        }
        else{
            return this->val>=myint.getVal();
        }
    }
    int getVal(){
        return val;
    }
private:
    int type;
    int val;
};

class Solution {
public:
    bool binaryTree = true;
    
    bool isValidBST(TreeNode* root) {
        Myint myMax(1);//表示無窮大無窮小第二個參數不用賦值,沒有用到
        Myint myMin(0);
        if(root && root->left==NULL && root->right==NULL)//只有根節點
        {
            binaryTree = true;
            return binaryTree;
        }
        validBST(root, myMin, myMax);
        return binaryTree;
    }
    
    void validBST(TreeNode* root, Myint left, Myint right){
        if(root == NULL)
            return;
        TreeNode* leftNode = root->left;
        TreeNode* rightNode = root->right;
        if(left>=root->val || right<=root->val)//看成開區間
        {
            binaryTree = false;
            return;
        }
        Myint rootVal(2, root->val);
        validBST(leftNode, left, rootVal);//不能減一root-val-1
        validBST(rightNode, rootVal, right);//不能加一root->val+1數據可能會溢出,看成開區間
    } 
};

結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章