BM34 判断是不是二叉搜索树
知识点树
描述
给定一个二叉树根节点,请你判断这棵树是不是二叉搜索树。
二叉搜索树满足每个节点的左子树上的所有节点均严格小于当前节点且右子树上的所有节点均严格大于当前节点。
例:图1
图2
数据范围:节点数量满足 ,节点上的值满足
示例1
输入:
{1,2,3}
复制返回值:
false
复制说明:
如题面图1
示例2
输入:
{2,1,3}
复制返回值:
true
复制说明:
如题面图2
题解
二叉搜索树是一种特殊的二叉树,它的每个节点值大于它的左子节点,且大于全部左子树的节点值,小于它右子节点,且小于全部右子树的节点值。因此二叉搜索树一定程度上算是一种排序结构。
递归实现-1
对于搜索二叉树中的任意一个节点,它的整个左子树的所有节点都小于当前节点的值,其右子树的所有节点都大于当前节点的值。实现步骤如下:
- 1. 如果根结点为空,返回true
- 2. 为根结点设置一个左右界限,作为起始条件
- 3. 判断当前节点与其左右界限的大小,如果当前节点的值不在该区间,则返回false
- 4.对当前节点的左子树、右子树进行递归判断,同时更新左右界限。对于左结点,其右界限需要更新为父节点的值;对于右子树,其左界限需要更新为父节点的值
代码实现如下:
// https://www.nowcoder.com/practice/a69242b39baf45dea217815c7dedb52b?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
bool is_valid_bst(TreeNode *root, int left, int right)
{
if (root == nullptr)
{
return true;
}
if (left >= root->val)
{
return false;
}
if (right <= root->val)
{
return false;
}
return is_valid_bst(root->left, left, root->val) && is_valid_bst(root->right, root->val, right);
}
bool isValidBST(TreeNode *root)
{
return is_valid_bst(root, INT_MIN, INT_MAX);
}
递归实现-2
一颗二茬搜索树的中序遍历是一个有序序列。如果我们对给定的二叉树进行中序遍历,并且记录当前节点的前驱结点,然后在访问当前节点的时候和前驱结点比较大小即可,实现如下:
long pre = INT_MIN;
//中序遍历
bool isValidBST(TreeNode *root)
{
if (root == NULL)
return true;
//先进入左子树
if (!isValidBST(root->left))
return false;
if (root->val <= pre)
return false;
//更新最值
pre = root->val;
//再进入右子树
if (!isValidBST(root->right))
return false;
return true;
}
非递归实现
非递归实现实际上可以通过非递归版本的中序遍历进行实现。分析从略.
注意:实际上可以通过一个前驱节点的保存来判断是否严格有序,从而省略掉中间数组。
代码如下:
bool isValidBST(TreeNode *root)
{
//设置栈用于遍历
stack<TreeNode *> s;
TreeNode *head = root;
vector<int> sort; //记录中序遍历的数组
while (head != NULL || !s.empty())
{
//直到没有左节点
while (head != NULL)
{
s.push(head);
head = head->left;
}
head = s.top();
s.pop();
//访问节点
sort.push_back(head->val);
head = head->right;
}
//遍历中序结果
for (int i = 1; i < sort.size(); i++)
{
//一旦有降序,则不是搜索树
if (sort[i - 1] > sort[i])
return false;
}
return true;
}