Leetcode98
1.问题描述
2.解决方案
注意点:本题也是二叉搜索树容易犯的两个错误
解法一:强行递归
二叉搜索树要求左子树所有结点必须小于根节点,右子树所有结点必须大于根节点
那么我的思路,遍历每一个结点,对于每一个结点我都判断这个结点的左右子树是否符合规则
1.judgeSmall和judgeBig和isValidBST三个递归函数都有很清晰一致的思路就是先判断当前节点再递归判断左右子树,这个思路我也希望能回来多看!!!把这种递归的思路刻在脑子里!!!
//--------1.第一步确定root这颗树没问题
//--------2.第二步确定root左右子树没问题
2.加上必要的检查比如root==nullptr应该返回什么等
class Solution {
public:
//整棵树必须都小于val
bool judgeSmall(TreeNode* root,int val){
if(root== nullptr) return true;
//1.第一步确定当前节点没问题
if(root->val>=val) return false;
//2.第二步确定左右子树没问题
return judgeSmall(root->left,val)&&judgeSmall(root->right,val);
}
//整棵树必须都大于val
bool judgeBig(TreeNode* root,int val){
if(root== nullptr) return true;
//1.第一步确定当前节点没问题
if(root->val<=val) return false;
//2.第二步确定左右子树没问题
return judgeBig(root->left,val)&&judgeBig(root->right,val);
}
bool isValidBST(TreeNode* root) {
if(root== nullptr) return true;
//1.第一步确定root这颗树没问题
if((judgeSmall(root->left,root->val)&& judgeBig(root->right,root->val))== false) return false;
//2.第二步确定root左右子树没问题
return isValidBST(root->left)&&isValidBST(root->right);
}
};
解法二:中序遍历递增
这是二叉搜索树一个很好的性质,中序遍历是递增的!
class Solution1 {
public:
vector<int> inorder;
void tran(TreeNode* root){
if(root== nullptr) return;
tran(root->left);
inorder.push_back(root->val);
tran(root->right);
}
bool isValidBST(TreeNode* root) {
tran(root);
for(int i=1;i<inorder.size();i++){
if(inorder[i-1]>=inorder[i]) return false;
}
return true;
}
};
解法三:中序遍历递归
1.其实解法三和解法二本质上是一样的都利用了中序遍历递增这一特性,只不过解法二是把中序列出来然后再判断递增,而解法三是在递归的过程中判断,递归遍历结束了结果也就出来了!
2.怎么说呢,是一个不同于之前的递归,之前的递归好像都是先判断root再递归左右子树,其实啊其实啊!之前我一直没强调这个事情,之前的递归都是默认前序遍历就可以解决了的,这个题当然不可以了,必须是中序遍历,所以以后递归还得看具体题目特点!
3.所以这个题的递归是不是解锁了新世界!
4.代码实现没什么好说的就是在递归的过程中一直判断一旦有非递增直接return false!
class Solution2 {
public:
long long maxValue=INT64_MIN;
bool isValidBST(TreeNode* root) {
if(root== nullptr) return true;
//1.先判断自己这符不符合
bool left=isValidBST(root->left);
if(root->val>maxValue) maxValue=root->val;
else return false;
bool right=isValidBST(root->right);
//2.再判断左右子树符不符合
return left&&right;
}
};
解法四:迭代法
就是把解法三的递归用迭代代替,这里暂时不给出!