给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:
2
/ \
1 3
输出: true
示例 2:
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
一、思路
(一)中序遍历
搜索二叉树的中序遍历结果是升序的,因此先对BST进行中序遍历,保存结果到向量中,再对向量的有序性进行判断即可
C++代码:
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (root == nullptr)
return true;
vector<int> nums;
InorderTraversal(root,nums);
return isOrder(nums);
}
void InorderTraversal(TreeNode* root, vector<int>& nums) {
if (root == nullptr)
return;
InorderTraversal(root->left, nums);
nums.push_back(root->val);
InorderTraversal(root->right, nums);
}
bool isOrder(vector<int>& nums) {
for (int i = 0; i < nums.size() - 1; i++)
if (nums[i] >= nums[i + 1])
return false;
return true;
}
};
执行效率:
(二)中序遍历之深度优先搜索
我们可不可以不在向量里面存放每个节点的数值,直接判断呢?
可以!!!
原来中序遍历是没有返回值的,现在要让它返回一个判断值。
其次中间的访问操作也要进行修改,不再是将根结点的数值放入向量,而是与前一个的根结点的数值进行比较,因为是先序,因此前一个根结点应该是当前根结点的左子树的根结点,所以要比当前根结点的值小。
C++代码:
class Solution {
public:
TreeNode* pre_root;
bool isValidBST(TreeNode* root) {
pre_root = NULL;
return isValid(root);
}
bool isValid(TreeNode* root) {
// 空树是一颗BST
if (root == NULL)
return true;
// 判断左子树是否为BST
if (!isValid(root->left))
return false;
// 判断当前根结点的值 与 其左子树根结点的值的大小
if (pre_root && pre_root->val >= root->val)
return false;
pre_root = root;
// 判断右子树是否为BST
if (!isValid(root->right))
return false;
return true;
}
};
执行效率:
不知道为什么没有任何提升。。。。囧