判是否是二叉排序树,看似想到递归来判,因为二叉树之类的都是递归定义,判定递归自然很好理解,结果发现挂了
if(root==NULL) return true;
if(root->left==NULL&&root->right!=NULL)
return (root->val<root->right->val) && isValidBST(root->left) && isValidBST(root->right);
if(root->right==NULL&&root->left!=NULL)
return (root->left->val<root->val) && isValidBST(root->left) && isValidBST(root->right);
if(root->left==NULL&&root->right==NULL)
return true;
return (root->left->val<root->val) && (root->val<root->right->val) && isValidBST(root->left) && isValidBST(root->right);
结果挂了,想不通,之前左右子树空的几种组合情况还没考虑,因为后面还有left right 访问val的语句。后来再看一遍定义,懂了。
虽说他是递归定义的,但是它是指整个左子树都小于根,整个右子树都大于根,如果只是左孩子右孩子小于大于根上面递归是没有问题的,但是现在不行,例如上述语句会把左孩子虽然是二叉排序树,但是有一个最大的比根大的二叉树包含进来,也即r->left->val< r->val, r->left->val< r->left最右下->val 这两句退不出 r->left最右下->val <r->val
简单说就是a<b, a<c 不能确定b c的关系,而这种如果出现非二叉排序树,上面代码已然判为true,于是仔细看定义发现问题了。
只能乖乖中序遍历,然后看是否单调递增排序,还不能非递减,因为定义是严格小于 大于
附上代码:
bool isValidBST(TreeNode *root) {
if(root==NULL) return true;
stack<TreeNode* > S;
//S.push(root);
TreeNode* p=root;
vector<int> order;
while(!S.empty()||p!=NULL)
{
while(p!=NULL)
{
S.push(p);
p=p->left;
}
p=S.top();
S.pop();
order.push_back(p->val);
p=p->right;
//if(S->right!=NULL)
// S.push(S->right);
//if(S->left!=NULL)
// S.push(S->left);
}
for(int i=0;i<order.size()-1;i++)
{
if(order.at(i)>=order.at(i+1))
return false;
}
return true;
/*
if(root==NULL) return true;
if(root->left==NULL&&root->right!=NULL)
return (root->val<root->right->val) && isValidBST(root->left) && isValidBST(root->right);
if(root->right==NULL&&root->left!=NULL)
return (root->left->val<root->val) && isValidBST(root->left) && isValidBST(root->right);
if(root->left==NULL&&root->right==NULL)
return true;
return (root->left->val<root->val) && (root->val<root->right->val) && isValidBST(root->left) && isValidBST(root->right);
*/
}
另外还有一道回文串,一开始学程舍就接触过的,这次不考虑非数字字母的字符,里面还是有越界判断又忘了,另外急于提交,连逻辑判断语句都写错了= =
bool isPalindrome(string s) {
int lefti=0,righti=s.length()-1;
while(lefti<righti)
{
while(lefti<righti &&!((s[lefti]<='z'&&s[lefti]>='a')||(s[lefti]<='Z'&&s[lefti]>='A')||(s[lefti]<='9'&&s[lefti]>='0')))
lefti++;
if(lefti==righti) return true;
while(righti>lefti &&!((s[righti]<='z'&&s[righti]>='a')||(s[righti]<='Z'&&s[righti]>='A')||(s[righti]<='9'&&s[righti]>='0')))
righti--;
if(lefti==righti) return true;
if(s[lefti]==s[righti]||s[lefti]+'A'-'a'==s[righti]||s[righti]+'A'-'a'==s[lefti])
{
lefti++;
righti--;
}
else
{
return false;
}
}
return true;
}
另外看到了里面lefti<righti 让我想到了让人不寒而栗的Hoarn版partition函数= =
今天偶然看到博客分析二叉树的性质,因为扩展到图的时候还是比较有用的。
1. ni 表示度数(孩子数)为i的结点个数,n为总结点数,m为边数或总度数
n2+n1+n0=n=m+1
2n2+n1=m
两式一减 n2-n0=-1 n0=n2+1
所以二叉树的叶子结点(终端结点,度为0的结点) 与度为2的结点的个数总是差一
2 i层有2^(i-1) 个结点
3 n个结点二叉树有 上界(log2(n+1)) 或下届(log2n)+1高度
4 高度为h的二叉树做多2^h-1个结点
http://blog.csdn.net/ab198604/article/details/8491370
5 有n+1 个空指针域 n个结点,m个边,m=n-1 共2n个指针域 所以剩n+1个指针域,这些域也是用来建线索二叉树,尽管想到那个繁琐的东西就头大= =