今天开始leetcode题解,又是一个没头没尾的开始,不知道能不能全部写完。
首先给大家分享一个典型的错误答案:
bool isValidBST(struct TreeNode* root) {
struct TreeNode* left;
struct TreeNode* right;
if(root==NULL||(root->left==NULL&&root->right==NULL)) return true;
while(root){
left = root->left;
right = root->right;
if(isValidBST(left)&&isValidBST(right)){
if(left!=NULL&&right!=NULL){
if(root->val>left->val&&root->val<right->val) return true;
else return false;
}else if(left==NULL){
if(root->val<right->val) return true;
else return false;
}else if(right==NULL){
if(root->val>left->val) return true;
else return false;
}else return true;
}
else return false;
}
return true;
}
第一反应就是递归的求解这一问题,首先判断两棵子树是不是二叉搜索树,若两棵子树都是二叉搜索树,则判断当前节点是否为二叉搜索树,但这一做法有一个问题,就是只能判断相邻层次的树是否为二叉搜索树,但对于层次不相邻的节点就无能为力了,比如其中一个测试用例就无法通过“ [10,5,15,null,null,6,20]”。
因此要解决这一问题,靠这种递归的思路是无法解决的,我也看到了一种递归的解法不过我并没有看懂。
分享一下我的做法:既然二叉搜索树满足根节点大于左子树的所有节点,小于右子树的所有节点,所以树的中序遍历一定满足数值递增这一性质。
因此对于这道题我的解法是:中序遍历二叉搜索树,得到遍历序列,从头到尾扫描序列,若出现逆序则返回false,否则返回true。
但这里在实现上要注意的一点是:使用递归的方法实现中序遍历可能在思路上比较清晰,实现起来也比较简单,但这一方法的问题在于遍历序列的存储比较复杂,同时需要借助全局变量对数据进行存储。因此这里应使用非递归的方法是对二叉树进行遍历。
二叉树的中序非递归遍历算法:
- 从根节点出发,遍历节点的左节点并入栈,若当前节点为空则停止;
- 判断当前栈是否为空,若不为空则出栈,同时遍历当前节点的右子树;
- 判断当前栈为空同时遍历指针也为空,若同时成立则算法结束;否则返回步骤1。
源码如下:
bool isValidBST(struct TreeNode* root) {
if(root==NULL) return true;
struct TreeNode** temp = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*100000);
int* result = (int*)malloc(sizeof(int)*100000);
struct TreeNode* pointer = root;
int i = 0;
int j = 0;
int length = 0;
do{
while(pointer!=NULL){
temp[i++] = pointer;
pointer = pointer->left;
}
if(i!=0){
pointer = temp[--i];
result[length++] = pointer->val;
pointer = pointer->right;
}
}while(pointer!=NULL||i!=0);
for(i=1;i<length;i++){
if(result[i-1]>=result[i]) return false;
}
return true;
}
由于树的中序非递归遍历需要借助栈,而c语言中不像c++中有现成的stack可以使用,因此直接使用数组模拟栈的功能,其实很简单就是数据的插入或删除均在栈的底端进行即可。之所以要申请这么大,是由于测试数据中存在这么大的输入数据。