面试算法系列- 07 二叉树的递归

07 二叉树的递归

可以解决面试中绝大多数的二叉树问题尤其是树型dp问题

本质是利用递归遍历二叉树的便利性

二叉树的递归套路

1)假设以X节点为头,假设可以向X左树和X右树要任何信息
2)在上一步的假设下,讨论以X为头节点的树,得到答案的可能性(最重要) 常见分类: 与x无关,与x有关

3)列出所有可能性后,确定到底需要向左树和右树要什么样的信息
4)把左树信息和右树信息求全集,就是任何一棵子树都需要返回的信息S
5)递归函数都返回S,每一棵子树都这么要求
6)写代码,在代码中考虑如何把左树的信息和右树信息整合出整棵树的信息

​ 难点:

​ 1、假设分类

​ 2、具体的可能性,需要什么具体信息

​ 3、如何实现递归函数

​ 1、base case
2、递归左右树
​ 3、加工该次如何返回要求信息

题目

1、isBalance

​ 给定一棵二叉树的头节点head,返回这颗二叉树是不是平衡二叉树

​ 1、列举全部可能

​ 1、) 左树

​ 树高

​ 是否为平衡二叉树

​ 2、)右树

​ 树高

​ 是否为平衡二叉树

​ 2、需要信息就是树高,和是否为平衡二叉树(画递归树)

	Info process(Node head){
    
    
        //base case
    if(x == null){
    
    
        return 0; //树高为0
    }
        //递归
	Info(x.left);
	Info(x.right);
        //处理该次的信息返回
	height = max(左树高,右树高) + 1;
	if(左树.isAK 
		&& 右树.isAK 
		&& abs(左树.height - 右树.height)<=1){
    
    
        Info(x).isAk = true;
		}
	}

2、is满二叉树

​ 给出一个head,返回这颗树是否是满二叉树

​ method1、暴力解法

​ 1、找到树高height

​ 2、遍历树节点个数nodes

​ 3、 if( nodes == (1>>height - 1)) yes else no

​ method2、树递归

举例所有的可能性:

​ 1、head左、右子树,

​ 树高 , 节点数

​ 所以info为树高、节点数

		Info  process(Node head){
    
    
		//base case
		if(head == null){
    
    
		return  new Info(0,0);
		}
		//递归
		process(head.left);
		process(head.right);
		//处理此次的信息
		int height  = max(process(head.left).height ,
		process(head.right).height ) + 1;
		int nodes = process(head(left).nodes
		+process(head(right).nodes+1;
		return  new  Info(height  ,nodes);
		}
		
		void isFull(){
    
    
			process(head);
			if(  nodes ==  (1>>height  - 1))    
			yes   else  no;
		}
		

3、is完全二叉树

method1、暴力解法

​ 情况1、有右孩子没有左孩子

​ 2、有左右孩子不双全,后序又出现孩子的情况!

​ 其余情况都是满足条件

​ 使用宽度优先遍历,之后使用flag1记录左右孩子不双全的情况,出现情况1、2就退出!

method2、树递归方法

​ 举例所有答案

​ 1、)满二叉树

​ 2、)有缺口

​ 1:左树没有撑满,右树为满二叉树

​ 2:左树撑满,但是没有到右树,左右树都是满二叉树

​ 3:左树撑满,右树为完全二叉树

​ 转为数学表达式:

​ 2.1 left.height - right.height = 1

​ 左.isCBT(完全) 右.isFull(满)

可能会需要的信息: 树的结点数,用于判断isFull。但是没有必要,因为,当左树,右树都是full,且高度差为0,该树必定为满二叉树。base case 时,full 为 true。所以之前的题可以用这个思想去优化!!!

​ 同理2.2 ,2.3都需要上述的height,isFull,isCBT的三个信息

public static class Info {
    
    
		public boolean isFull; //满
		public boolean isCBT; //完全
		public int height; //高度

		public Info(boolean full, boolean cbt, int h) {
    
    
			isFull = full;
			isCBT = cbt;
			height = h;
		}
	}
Info  process(Node head){
    
    
		//base case
		if(head == null){
    
    
		return new  
		}	
		//递归
		Info leftInfo = process(head.left);
		Info rightInfo = process(head.right);
		//处理次次消息
		int height = max(leftInfo.height ,
		rightInfo.height ) + 1;
		
		boolean isFull =false;
		if(leftInfo.isFull
        &&
		rightInfo.isFull
		&&
		leftInfo.height
        == 
       rightInfo.height){
    
     isFull = true;}
		
		isCBT = false ;
		if(isFull){
    
    
			isCBT = true;
		}else{
    
    
		//1
		if( leftInfo.isCBT 
		&&  
		rightInfo.isFull
		&&
		leftInfo.height -	
		rightInfo.height ==  1){
    
    isCBT = true;}
		//2
		if(leftInfo.isFull
		&&  
		rightInfo.isFull
		&&
		leftInfo.height -	
		rightInfo.height ==  1){
    
    isCBT = true;}
		//3
		if(leftInfo.isFull
		&&  
		rightInfo.isCBT
		&&
		leftInfo.height -	
		rightInfo.height ==  0{
    
    isCBT = true;}
		}
		return Info(isFull, isCBT, height);

}

4、返回最大距离

​ 给定一棵二叉树的头节点head,任何两个节点之间都存在距离,返回整棵二叉树的最大距离

1、)最大距离 列举答案所有可能假设分类:

​ 1、与head无关

​ 需要左最大距离,左max

​ 需要右最大距离,右max

​ 最大距离 = (左max,右max)

​ 2、与head有关

​ 换言之就是俩棵最深树的距离

​ 最大距离 = 左树高+1+右树高

​ 树高 = max(左数高 ,右树高) + 1

3种情况

2、)需要信息

​ 1、树的高度

​ 2、点的最大距离

Info process(Node x){
    
    
    //base case
    if(x == null){
    
    
        return  new Info( 0 ,0);
    }
    //递归
	Info(x.left);
	Info(x.right);
    //处理本次的信息sf
    
	height = max(左树高,右树高) + 1;
    distance = 左树高 + 右树高 + 1 ;
	maxDistance = max(distance,max(Info(x.left).maxDistance,Info(x.right).maxDistance))
       return  new Info(height , maxDistance)
}

剩下的举例见算法题!

5、公共父节点

​ 给定一棵二叉树的头节点head,和另外两个节点o1和o2。返回o1和o2的最低公共祖先

​ method1、暴力解

​ 1、使用map记录每个键值对<子节点,父节点>

​ 2、使用set,将a的节点的所有父节点加入set

​ 3、遍历b的父节点,set.contain(b.父节点) 判断是否有重复

​ method2、二叉树递归

​ 分析所有答案情况:

​ 1、 o1,o2不在head

​ 2、 o1,o2有一个在head的子树上 (都没有交汇)

​ 3、o1,o2都在head的子树上 (必有交汇点)

​ 1)全在左子树

​ 2)全在右子树

​ 3)左右个一个

​ 4)o1 or o2为head

需要的信息:

树上有无o1,o2,交汇点

public static class Info {
    
    
   //第一个交会的父节点
   public Node ans;
   //发现01
   public boolean findO1;
   //发现02
   public boolean findO2;

   public Info(Node a, boolean f1, boolean f2) {
    
    
      ans = a;
      findO1 = f1;
      findO2 = f2;
   }
}
Info process(Node head){
    
    
	//base case
	if(head  == null){
    
    
	return new Info(null,false,false);
	}
		Info leftInfo = process(head.left);
		Info rightInfo = process(head.right);
	//3信息
		boolean findO1 = head == o1 || leftInfo.findO1 || rightInfo.findO1;
		boolean findO2 = head == o2 || leftInfo.findO2 || rightInfo.findO2;
	//3信息整合才是上述简要概括
	
}

猜你喜欢

转载自blog.csdn.net/huihui5210/article/details/111220519
今日推荐