一、算法描述
给定一个二叉树根节点,请你判断这棵树是不是二叉搜索树。
二叉搜索树满足每个节点的左子树上的所有节点均小于当前节点且右子树上的所有节点均大于当前节点。
示例1
输入:{1,2,3}
返回值:false
示例2
输入:{2,1,3}
返回值:true
二、解题思路
在这个算法中,我们设置了一个最小值和最大值,初始值分别为LONG_MIN和LONG_MAX。这是因为树中的节点值有可能是int类型的最小值或最大值,因此要使用较小的最小值和较大的最大值,避免值溢出。
在helper函数中,如果节点为空,则该节点为二叉搜索树,返回true;如果当前节点的值小于最小值或大于最大值,则不是二叉搜索树,返回false。如果当前节点的值满足条件,则递归判断其左子树和右子树是否为二叉搜索树。如果左右子树均为二叉搜索树,则返回true,否则返回false。在递归判断左右子树时,需要更新子节点的最小值和最大值。对于左子树,最大值应为当前节点的值;对于右子树,最小值应为当前节点的值。这是因为对于任意节点,其左子树的所有节点的值都小于当前节点的值,而右子树的所有节点的值都大于当前节点的值。
最后,我们在主函数中构造了一棵二叉搜索树,并调用isValidBST函数判断是否为二叉搜索树。如果是,则输出"The given binary tree is a binary search tree";否则输出"The given binary tree is not a binary search tree"。
该算法的时间复杂度为O(n),其中n是树中节点的数量。算法的空间复杂度取决于递归的深度,因此为O(h),其中h是树的高度。在最坏情况下,当树退化为链表时,h = n,因此空间复杂度为O(n)。
三、C++代码实现
#include <iostream>
using namespace std;
// 定义二叉树的节点结构体
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
bool isValidBST(TreeNode* root) {
// 设置一个较小的最小值和一个较大的最大值
return helper(root, LONG_MIN, LONG_MAX);
}
// 使用递归判断二叉树是否为二叉搜索树
bool helper(TreeNode* root, long long minVal, long long maxVal) {
// 如果节点为空,则该节点为二叉搜索树,返回true
if (root == NULL) {
return true;
}
// 如果当前节点的值小于最小值或大于最大值,则不是二叉搜索树,返回false
if (root->val <= minVal || root->val >= maxVal) {
return false;
}
// 递归判断左子树和右子树是否为二叉搜索树
return helper(root->left, minVal, root->val) && helper(root->right, root->val, maxVal);
}
};
int main() {
// 测试样例
TreeNode* root = new TreeNode(5);
root->left = new TreeNode(1);
root->right = new TreeNode(4);
root->right->left = new TreeNode(3);
root->right->right = new TreeNode(6);
Solution s;
if (s.isValidBST(root)) {
cout << "The given binary tree is a binary search tree" << endl;
} else {
cout << "The given binary tree is not a binary search tree" << endl;
}
return 0;
}