问题 Medium
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
- The left subtree of a node contains only nodes with keys less than the node’s key.
- The right subtree of a node contains only nodes with keys greater than the node’s key.
- Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Binary tree [2,1,3], return true.
Example 2:
1
/ \
2 3
Binary tree [1,2,3], return false.
分析
- 刚开始我想的是使用递归,比较每个节点和它的左右孩子,后来发现这种方法不对,因为有的树,比如左孩子确实比该节点小,但是左孩子的右孩子比该节点大,这种情况就无法判断出来。
- 后来还是使用最常规的方法,就是下面方法的第一种,因为BST的中序遍历是一个从小到大的有序数列,所以先采用简单的递归方式完成中序遍历得到数组,然后扫描一遍数组确定是否从小到大,若不是,则说明不是BST。这里面做了两次时间复杂度为O(n)的运算。
- 下面第二种方法,不再使用递归法完成中序遍历,而是使用迭代法,这样一来就能在迭代的过程中去验证是否每一个值都比前一个值小。这样做的好处是,可能树还没有遍历完,就能发现这不是BST,且后面也不用再扫描数组,故速度快。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
//方法一:思想是判断中序遍历之后的数组如果不是有序数组,则不是BST
vector<int> result;
void MidOrder(TreeNode* root)
{
if(root)
{
if(root->left) MidOrder(root->left);
result.push_back(root->val);
if(root->right) MidOrder(root->right);
}
}
bool isOrder(vector<int> &nums)
{
if(nums.size() == 0) return true;
for(int i=0; i<nums.size()-1; i++) //需要先在前一行处理size==0的情况,不然 nums.size()-1 会出错,详见参考。
if(nums[i] >= nums[i+1])
return false;
return true;
}
bool isValidBST(TreeNode* root) {
if(root) MidOrder(root);
return isOrder(result);
}
//方法二:上面采用递归的方式中序遍历BST,现在采用迭代的方式遍历,
//能够直接在迭代过程中完成检查,不一定需要遍历完整棵树,所以更快。
//这种迭代 来中序遍历树的方法能够用在很多地方。
bool isValidBST(TreeNode* root) {
if(root == NULL) return true;
stack<TreeNode*> stack;
TreeNode* previous = NULL; //必须初始化为NULL
while(root || !stack.empty())
{
while(root)
{
stack.push(root);
root = root->left;
}
root = stack.top();
if(previous != NULL && (previous->val >= root->val)) return false;
previous = root; //有人不加上面一行判断和这行赋值,直接一开始就将用来比较的值初始化为INT_MIN之类,不好
root = root->right;
stack.pop();
}
return true;
}
};
总结
1.上述第一种方法中,isOrder()函数内,在使用 i