二叉搜索树中的众数
既然是搜索树,中序遍历就是有序的
思路:从头遍历有序数组元素出现的频率,相邻两个元素作比较,把出现频率最高的元素输出。
技巧:1.使用两个指针 pre指针和cur指针 初始时pre=null,所以pre=null时便是比较的第一个元素。
2.众数很有可能不止一个,所以需要一个数组来存放众数
3.只需遍历一遍。若count==maxcount,则把这个元素加入到结果集中。
若 count>maxcount,清空结果集,元素加入结果集,maxcount=count
需要全局定义
1.结果集 2.数组集 3.count 4.maxcount
完整代码如下:
递归法
class Solution {
ArrayList<Integer> reslist;
int maxcount;
int count;
TreeNode pre;
public int[] findMode(TreeNode root) {
reslist =new ArrayList<>();
maxcount=0;
count=0;
pre=null;
findMode1(root);
int[] list=new int[reslist.size()];
for(int i=0;i<reslist.size();i++){
list[i]=reslist.get(i);
}
return list;
}
public void findMode1(TreeNode root){
if(root==null)return;
findMode1(root.left);
if(pre==null||root.val!=pre.val){
count=1;
}else{
count++;
}
if(count>maxcount){
reslist.clear();
reslist.add(root.val);
maxcount=count;
}else if(count==maxcount){
reslist.add(root.val);
}
pre=root;
findMode1(root.right);
}
}
二叉树的最近公共祖先
返回节点p和节点q的公共祖先
思路:自底向上查找(回溯) ,后序遍历则是天然的回溯过程。
如何判断一个节点是节点p和节点q的公共祖先呢?
答:如果找到一个节点,发现左(右)子树出现节点p,右(左)子树出现节点q,那么该节点就是最近的公共祖先。
递归法
1.确定递归函数参数以及返回值
参数:treenode root ,p,q
返回值:最近的公共祖先
2.确定终止条件
若找到节点p或者q,或者遇到空节点,就返回
3.确定单层递归逻辑
本题要遍历树的所有节点
注意:如果left 和 right都不为空,说明此时root就是最近公共节点。
如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然
不懂的话可见下图:
完整代码如下:
递归法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||root==p||root==q){
return root;
}
TreeNode left=lowestCommonAncestor(root.left,p,q);
TreeNode right=lowestCommonAncestor(root.right,p,q);
if(left==null&&right==null){
return null;
}else if(left!=null&&right==null){
return left;
}else if(left==null&&right!=null){
return right;
}else{
return root;
}
}
}
二叉搜索树的最近公共祖先
要比普通二叉树的公共祖先问题简单得多。
不需要使用回溯,因为二叉搜索树自带方向性。所以我们可以使用前序遍历。(其实遍历顺序无所谓,因为没有中节点的处理逻辑)
而且不需要遍历整棵树,找到结果则直接返回
完整代码如下:
递归法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root.val>p.val&&root.val>q.val)return lowestCommonAncestor(root.left,p,q);
if(root.val<p.val&&root.val<q.val)return lowestCommonAncestor(root.right,p,q);
return root;
}
}
迭代法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(true){
if(root.val>p.val&&root.val>q.val){
root=root.left;
}else if(root.val<p.val&&root.val<q.val){
root=root.right;
}else{
break;
}
}
return root;
}
}
二叉搜索树中的插入操作
思路:本体其实并不复杂,不需要考虑改变树的结构的插入方式。
只需要遍历二叉树,找到空节点插入元素即可。
递归法
1.确定递归函数参数及返回值
参数:根节点指针 要插入的元素
返回值可有可无
2.确定终止条件
遍历节点为null时,即是要插入节点的位置,并把插入的节点返回
3.确定单层递归的逻辑
因为是搜索树,所以不需要完整的遍历整棵树
因为是有方向的,则可以根据插入元素的数值决定递归的方向
即if(root.val>val) root.left
if (root.val<val) root.right
完整代码如下:
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root==null){
return new TreeNode(val);
}
if(root.val<val){
root.right=insertIntoBST(root.right,val);
}else if(root.val>val){
root.left=insertIntoBST(root.left,val);
}
return root;
}
}
迭代法
需要一个指针pre来记录空节点之前的节点,这样才好判断插入的元素是插入左侧还是右侧
需要一个newroot来返回最后插入新元素的root
完整代码如下:
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root==null){
return new TreeNode(val);
}
TreeNode newroot=root;
TreeNode pre=root;
while(root!=null){
pre=root;
if(root.val>val){
root=root.left;
}else if(root.val<val){
root=root.right;
}
}
if(pre.val>val){
pre.left=new TreeNode(val);
}else if(pre.val<val){
pre.right=new TreeNode(val);
}
return newroot;
}
}