題目鏈接
【題目】
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.
【解析】
題意:判斷一個二叉樹是否爲二分查找樹。
何爲二分查找樹?1) 左子樹的值都比根節點小;2) 右子樹的值都比根節點大;3) 左右子樹也必須滿足上面兩個條件。
C++
(1)中序遍歷,暴力遞歸(AC)【慢】
class Solution {
public:
bool isValidBST(TreeNode* root) {
if(root == NULL) return true;
if(!valid_left(root->left, root->val)||!valid_right(root->right,root->val)) return false;
return (isValidBST(root->left) && isValidBST(root->right));
}
bool valid_left(TreeNode* root, int value){
if(root == NULL ) return true;
if(root->val >= value) return false;
return valid_left(root->left,value)&&valid_left(root->right,value);
}
bool valid_right(TreeNode* root, int value){
if(root == NULL ) return true;
if(root->val <= value) return false;
return valid_right(root->left,value)&&valid_right(root->right,value);
}
};
(2)最大最小值比較,遞歸(Not AC)網上有人說以前是可以AC的
class Solution {
public:
bool isValidBST(TreeNode* root) {
return min_max_judge(root,INT_MIN,INT_MAX);
}
bool min_max_judge(TreeNode* root,int min_value, int max_value){
if(root == NULL) return true;
if(root->val < max_value && root->val > min_value && (min_max_judge(root->left,min_value,root->val) && min_max_judge(root->right,root->val, max_value)))
return true;
else
return false;
}
}
(3)通過vector存中序遍歷的val,然後從頭到尾判斷是否滿足遞增
因爲中序遍歷所經過的點的值必然是從小到大的(AC)【較快】
class Solution {
public:
vector<int> oder_vector;
bool isValidBST(TreeNode* root) {
if(root==NULL) return true;
if(root->left==NULL&&root->right==NULL) return true;
oder_search(root,oder_vector);
for(int i=1;i<oder_vector.size();i++)
if(oder_vector[i] <= oder_vector[i-1]) return false;
return true;
}
void oder_search(TreeNode* root,vector<int>& oder_vector){
if(root==NULL) return;
oder_search(root->left,oder_vector);
oder_vector.push_back(root->val);
oder_search(root->right,oder_vector);
}
};
(4)優化(3),改成一種空間複雜度爲O(1)的方法(AC)【很快】
每次用pre記錄上一個遍歷的點,然後比較當前點的val與pre的大小,一旦出現root->val <= pre時候立馬退出,快了很多
這裏要注意的點就是,如果單純初始pre=INT_MIN的話,我們並不知道整棵樹最左邊的點是否比INT_MIN大,萬一剛好等於INT_MIN呢就出錯了,檢測了一下發現,leetcode上面的樣例真的有最左邊爲INT_MIN的,666
所以加了一個判斷flag1 = true,第一次過後就變成false,使得pre變成整棵樹最左邊的值
class Solution {
public:
bool isValidBST(TreeNode* root) {
if(root==NULL) return true;
if(root->left==NULL&&root->right==NULL) return true;
int flag = 0;
bool flag1 = true;
int pre = INT_MIN;
oder_search(root,flag,pre,flag1);
if(flag == 1) return false;
return true;
}
void oder_search(TreeNode* root,int & flag,int& pre,bool& flag1){
if(root==NULL) return;
oder_search(root->left,flag,pre,flag1);
if(flag1)
{
pre = root->val;
flag1 = false;
}
else
{
if(root->val <= pre){
flag = 1;
return;
}
pre = root->val;
}
oder_search(root->right,flag,pre,flag1);
}
};
python
(1)最大最小值:
python是可以AC的,【慢】
注意
-2**31要減1
2**31不能減1
其實就是爲了防止inf的問題啦,你可以試試去掉時通不過的樣例
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root):
return self.min_max_search(root,-2**31-1,2**31)#注意測試樣例
def min_max_search(self, root, min, max):
if root is None:
return True
return root.val < max and root.val > min and self.min_max_search(root.left,min,root.val) and self.min_max_search(root.right,root.val,max)
(2)C++方法(4)的python版本啦,一股氣寫的,有點粗糙(AC)
class Solution(object):
def oder_search(self,root,flags,pres,flag1s):
global flag
global flag1
global pre
flag = flags
flag1 = flag1s
pre = pres
if root is None:
return
self.oder_search(root.left,flag,pre,flag1)
if(flag1):
pre = root.val
flag1 = False
else:
if root.val <= pre:
flag = 1
return
pre = root.val
self.oder_search(root.right,flag,pre,flag1)
def isValidBST(self, root):
global flag
global flag1
global pre
if root is None:
return True
if root.left == None and root.right == None:
return True
flag = 0
pre = 0
flag1 = True
self.oder_search(root,flag,pre,flag1)
if flag is 1:
return False
return True
"""
:type root: TreeNode
:rtype: bool
"""
(3)當然,仔細想想可以將(2)的代碼精簡一下(AC):
class Solution(object):
value = None
def isValidBST(self, root):
if root is None:
return True
ans = self.isValidBST(root.left)
if(self.value is None):
self.value = root.val
else:
if root.val <= self.value:
ans = False
self.value = root.val
ans = ans and self.isValidBST(root.right)
return ans
然後才發現,精簡後並不是立馬退出,尷尬,哈哈