题目原代码和图解已上传至我的码云
题目描述:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
思路求解
这里我们首先要了解一下什么是二叉搜索树,我刚拿到这个定义误以为只需要根结点的左结点小于当前结点和右结点大于当前结点就行了
所以我第一次写出了以下的错误代码
这是我脑中构思出的判断思路
bool isValidBST(struct TreeNode* root){
if(root->left==root->right)
return true;
if(!root->left)
{
if(root->right->val<=root->val)
return false;
else
return true;
}
if(!root->right)
{
if(root->left->val>=root->val)
return false;
else
return true;
}
else
{
if(root->left->val>=root->val||root->right->val<=root->val)
return false;
}
return isValidBST(root->left)&&isValidBST(root->right);
}
果然没有给我过
这一步,我走读了许多遍代码,甚至画了逻辑展开图,发现这个代码能够清晰地表达我的逻辑
所以应该不是代码的问题肯定是我对搜索二叉树的理解出现了问题
仔细观察测试用例,发现与上面的树特征差不多
到底是哪里出现问题了呢?
我们需要重新读一下完全二叉树的定义,我当时特地百度了一下完全二叉树的官方定义
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
注意这里划重点,是子树的所有结点!
所以当时我应该犯了这种错误
这个3结点比8小是没有问题的,但它站在根结点5的角度来说,应该比5大才对!
原来,果然是我对搜索二叉树的理解出现了问题
那么,既然每个结点是有严格的范围要求的,那我们可以考虑:在检查每一个结点的时候,检查它是否在它应该在的范围内
就拿3这个结点来说
它的范围就应该在3-8之间
我们在这里可以调用递归用的子函数,传参传一个最小范围和最大范围,每次递归左树的时候,缩小它的最大值,调用右数缩小它的最小值
画图求解:
代码实现:
bool _Vaild(struct TreeNode* root,long lower,long upper)
{
if(!root)
return true;
if(root->val<=lower||root->val>=upper)
return false;//不符合范围要求
return _Vaild(root->left,lower,root->val)&&_Vaild(root->right,root->val,upper);//左子树要小所以更新最大值,右子树要大所以更新最小值
}
bool isValidBST(struct TreeNode* root){
return _Vaild(root,LONG_MIN,LONG_MAX);//这里是根结点,不限制范围
}