原题地址:https://leetcode.com/problems/validate-binary-search-tree/
题目描述
Given a binary tree, determine if it is a valid binary search tree (BST).
给出一个二叉树,判断其是否是合法的二叉查找树。
解题思路
首先,我们来看二叉查找树的定义:
- 根节点的左子树上所有节点的值都小于根节点的值
- 根节点的右子树上所有节点的值都大于根节点的值
- 左右子树分别都是二叉查找树
接下来,我们就可以很容易的写出一个递归方法来实现上述算法。
解法一
此种方法紧扣定义,我们假设有两个方法noGreater和noLess分别判定左右子树上左右节点的值分别不小于、不大于根节点的值,然后递归判断左右子树是否为二叉查找树。
算法描述
- 如果root为空返回true;
- 判断左子树上所有节点的值都小于根节点的值和右子树上所有节点的值都大于根节点的值是否同时成立,如果成立,则递归判断左右子树是二叉查找树是否同时成立,否则返回false。
分析
算法时间复杂度O(n^2),空间复杂度O(c)
代码
/** * 验证二叉树是否为合法的二插查找树 */
bool isValidBST(struct TreeNode *root) {
bool noGreater(struct TreeNode *, int);
bool noLess(struct TreeNode *, int);
// 空,返回true
if (root == NULL) return true;
// 判断:
// 1.左子树上所有节点的值都小于根节点的值
// 2.右子树上所有节点的值都大于根节点的值
if (noGreater(root->left, root->val) && noLess(root->right, root->val))
// 如果同时成立则,递归判断左右子树是二叉查找树是否同时成立
return isValidBST(root->left) && isValidBST(root->right);
else
// 如果不同时成立,返回false
return false;
}
/** * 判断以root为根节点的二叉树上的所有节点的值是否都大于val */
bool noLess(struct TreeNode *root, int val) {
// 空,返回true
if (root == NULL)
return true;
// 如果根节点的值不大于val,返回false
if (root->val <= val)
return false;
// 递归判定root的左右子树上的所有节点值是否都大于val
return noLess(root->left, val) && noLess(root->right, val);
}
/** * 判断以root为根节点的二叉树上的所有节点的值是否都小于val */
bool noGreater(struct TreeNode *root, int val) {
// 空,返回true
if (root == NULL)
return true;
// 如果根节点的值不小于val,返回false
if (root->val >= val)
return false;
// 递归判定root的左右子树上的所有节点值是否都小于val
return noGreater(root->left, val) && noGreater(root->right, val);
}
运行情况
Status:Accept
Time:12ms
解法二
那我们有没有一种方法只遍历二叉树一次呢?
有!
我们来观察二叉查找树,可以发现二叉查找树的一个特点,那就二叉查找树中序遍历可以得到一个递增的序列,现在事情变得简单起来,我们只需中序遍历二叉树,判断其序列是否递增即可。
算法描述
中序遍历二叉树,判断结果序列是否递增
分析
中序遍历只遍历二叉树一次,算法时间复杂度O(n),空间复杂度O(c)
代码
/** * 验证二叉树是否为合法的二插查找树 */
bool isValidBST(struct TreeNode *root) {
bool inorderTraversal(struct TreeNode *, int *, bool *);
int last; // 用来存储中序遍历时的上一个点
bool isFirst = true;// 用来表示是否为中序遍历获取到的第一个点
//中序遍历二叉树,看其是否递增
return inorderTraversal(root, &last, &isFirst);
}
/** * 中序遍历二叉树,看其是否递增 */
bool inorderTraversal(struct TreeNode *root, int *last, bool *isFirst) {
// 空,返回true
if (root == NULL)
return true;
/* 中序遍历左子树 */
if (root->left != NULL) // 这个判断语句可以没有
// 如果左子树中序遍历序列不递增,返回false
if (!inorderTraversal(root->left, last, isFirst))
return false;
/* 遍历当前节点 */
if (*isFirst) { // 如果当前节点是中序遍历获得的第一个节点
*isFirst = false; // 修改标志位
*last = root->val;// 更新中序遍历过程中上一个点的值
} else { // 如果当前节点不是中序遍历获得的第一个节点
if (*last >= root->val) // 判断当前节点是否大于遍历的上一个点
return false; // 当前节点不大于上一个点,返回false
else // 当前节点大于上一个点,更新中序遍历过程中上一个点的值
*last = root->val;
}
/* 中序遍历左子树 */
if (root->right != NULL) // 这个判断语句可以没有
// 如果右子树中序遍历序列不递增,返回false
if(!inorderTraversal(root->right, last, isFirst))
return false;
// 执行至此,说明中序遍历序列递增,返回true
return true;
}
运行情况
Status:Accept
Time:8ms
// 个人学习记录,若有错误请指正,大神勿喷
// sfg1991@163.com
// 2015-05-27