leetcode 501 二叉搜素树中的众数
对二叉搜索树的性质还不是很熟悉,不懂得利用其性质,做题没有方法论,这是暴露出来的问题,明天重做一下98,530,501这三个题,再进行总结
98这题,验证是否是二叉搜索树,首先是利用其性质:二叉搜索树在中序遍历的时候是有序的,从这里下手,我们只需要遍历看看是否有序即可
图中这种写法是随想录的,但是效率还不如常规写法,他那种写法不一定想得到,我们讲一下常规写法
bool traverse(TreeNode*root)
{
stack<TreeNode*>sta;
TreeNode*cur=root;
TreeNode*pre=nullptr;
while(cur||!sta.empty())
{
if(cur)
{
sta.push(cur);
cur=cur->left;//左
}
else
{
cur=sta.top();
sta.pop();
if(pre)//中
{if(cur->val<=pre->val)return false;}
pre=cur;
cur=cur->right;//右
}
}
return true;
}
常规是用一个栈来存放节点,进行中序遍历,在中的时候进行验证操作(一般的题目都是在中处进行修改以完成目的,其他部分是不变的),这里是验证其是否有序,已经是最简单的一种了,二叉搜索可以像广度遍历一样套模板
530这题也一样,只不过是把中序时所执行的操作改变了一下
501这题复杂一点,需要统计数出现的频率还有最大频率,搞清楚机制很重要:第一个数因为没有前驱所以count=1;当有pre的时候如果pre==cur那count加一,当pre!=cur说明节点不同count重置为1;接下来就是插入操作,当count==maxcount时插入数组,说明是答案之一,当有count>maxcount时前面的答案不符合要求需要清空数组
这三道题一连刷下来感觉还是不错的,对二叉搜索树有了更深的理解
leetcode 236 二叉树的最近公共祖先
这题和235线索二叉树算是一对姐妹题,这里我分别讲一下
首先是对题意的理解,题目要求是找最近的祖先,所以用自底向上的查找是最快的,自底向上也就是我们的后序遍历(回溯),把最终的结果返回到第一个节点root(不需要用到其他的数据结构,这个想不到就是想不到了,思维问题)
设计递归算法,按照三部曲:结束条件,调用参数,单层递归的方式去设计
结束条件:cur为空,left不为空(左子树),right不为空(右子树)
调用参数:也就是我们的root,p,q
单层递归:按左右中的方式遍历,先设置left,right表示左右子树的递归,再进行中的处理,如果左右都为空则返回空;左右有一个不为空(也就是找到了p,q),将不为空的返回;左右都不为空说明当前节点就是最近祖先
if(traverse)……与bool left=traverse的区别
首先递归是分有有返回值的和无返回值的
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值(236)
如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回
回到问题,if(traverse)是用来搜索其中一条符合条件的路径的,bool(或其他类型)left=traverse()是用来搜索整颗二叉树的
235这题就稍微有点和上一题不同,看到二叉搜索树首先就要想到中序遍历,因为中序遍历时二叉搜索树是有序的,利用这个特性我们就可以找到祖先
设置一个cur移动指针用来遍历二叉树,初值为root,当cur不在pq范围内就进行相应的调整,如果cur在pq范围内或者cur等于pq则说明是祖先,本质上是自上到下的查找,可以把搜索二叉树想象成一个数组