二叉树的递归套路

二叉树的递归套路可以解决绝大多数的二叉树问题尤其是树形dp问题,本质是利用递归遍历二叉树的便利性

问题一:

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

满足条件:①左树是平衡的;②右树是平衡的;③左树与右树的高度差不超过1;

package tree;

public class IsBalanced {
	
	public static class Node{
		public int value;
		public Node left;
		public Node right;
		
		public Node(int data) {
			this.value=data;
		}
	}
	
	
	public static boolean isBalanced(Node head) {
		return process(head).isBalanced;
	}
	
	
	//左右要求一样,info信息返回的结构体(一共返回两个信息)
	public static class Info{
		public boolean isBalanced;
		public int height;
		
		public Info(boolean b,int h) {
			isBalanced=b;
			height=h;
		}
	}
	
	//Node X:以X为头的树
	public static Info process(Node X) {
		if(X==null) {
			return new Info(true,0);
		}
		Info leftInfo=process(X.left);
		Info rightInfo=process(X.right);
		
		int height=Math.max(leftInfo.height, rightInfo.height)+1;
		
		boolean isBalanced=true;
		if(!leftInfo.isBalanced || !rightInfo.isBalanced || Math.abs(leftInfo.height-rightInfo.height)>1) {
			isBalanced=false;
		}
		return new Info(isBalanced, height);
	}
	


	public static void main(String[] args) {
	}

}

问题二:

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

分为两类:

①最大距离与当前节点无关,则最大距离=max{左树最大距离,右树最大距离}

②最大距离与当前节点有关,即左树最远的点到右树最远的点(左树高度+1+右树高度)

要求:左树返回离自己最大的距离及高度,右树返回离自己最大的距离及高度

package tree;

public class MaxDistance {
	
	
	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int data) {
			this.value = data;
		}
	}
	
	public static int maxDistance(Node head) {
		return process(head).maxDistance;
	}
	
	public static class Info {
		public int maxDistance;
		public int height;

		public Info(int dis, int h) {
			maxDistance = dis;
			height = h;
		}
	}

	public static Info process(Node X) {
		if (X == null) {
			return new Info(0, 0);
		}
		Info leftInfo = process(X.left);
		Info rightInfo = process(X.right);
		
		int height = Math.max(leftInfo.height, rightInfo.height) + 1;
		
		int maxDistance = Math.max(
				Math.max(leftInfo.maxDistance, rightInfo.maxDistance),
				leftInfo.height + rightInfo.height + 1);
		
		return new Info(maxDistance, height);
	}
	
	

	public static void main(String[] args) {
		
	}

}

问题三:

定个一颗二叉树的头结点head,返回这颗二叉树中最大的二叉搜索子树的头结点

①与当前节点无关

②与当前节点有关,即当前节点的左树和右树整体都是搜索二叉树,且左树的最大值小于X,右树的最小值大于X

要求:左树的最大子搜索二叉树的大小;左树整体是不是搜索二叉树,左树上的最大值;

           右树的最大子搜索二叉树的大小;右树整体是不是搜索二叉树,右树上的最小值;

故需要的信息即是要求的全集:最大子搜索二叉树的大小;是不是搜索二叉树;最大值,最小值

package tree;

public class MaxSubBSTSize {
	
	
	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int data) {
			this.value = data;
		}
	}
	
	public static int maxSubBSTSize(Node head) {
		if(head==null) {
			return 0;
		}
		return process(head).maxSubBSTSize;
	}
	
	
	public static class Info {
		public boolean isAllBST;
		public int maxSubBSTSize;
		public int max;
		public int min;

		public Info(boolean is,int size,int mi,int ma) {
			isAllBST=is;
			maxSubBSTSize=size;
			max=ma;
			min=mi;
		}
	}
	
	
	public static Info process(Node X) {
		if (X == null) {
			return null;
		}
		Info leftInfo = process(X.left);
		Info rightInfo = process(X.right);
		
		
		int min=X.value;
		int max=X.value;
		
		if(leftInfo!=null) {
			min=Math.min(min,  leftInfo.min);
			max=Math.max(max,  leftInfo.max);
		}
		if(rightInfo!=null) {
			min=Math.min(min,  rightInfo.min);
			max=Math.max(max,  rightInfo.max);
		}
		
		
		int maxSubBSTSize=0;
		if(leftInfo!=null) {
			maxSubBSTSize=leftInfo.maxSubBSTSize;
		}
		if(rightInfo!=null) {
			maxSubBSTSize=Math.max(maxSubBSTSize,rightInfo.maxSubBSTSize);
		}
		

		
		boolean isAllBST=false;
		if(
				//左树整体需要是搜索二叉树
				(leftInfo==null?true:leftInfo.isAllBST)
				&&
				(rightInfo==null?true:rightInfo.isAllBST)
				&&
				//左树最大值<x
				(leftInfo==null?true:leftInfo.max<X.value)
				&&
				(rightInfo==null?true:rightInfo.min>X.value)
				) {
			
			maxSubBSTSize=
					(leftInfo==null?0:leftInfo.maxSubBSTSize)
					+(rightInfo==null?0:rightInfo.maxSubBSTSize)
					+1;
			isAllBST=true;
			
		}
		
		return new Info(isAllBST,maxSubBSTSize,min,max);
	}
	

	public static void main(String[] args) {
		

	}

}

问题四:

派对的最大快乐值问题

员工信息的定义如下:

class Employee{
    public int happy;// 这名员工可以带来的快乐值
    List<Employee> subordinates;// 这名员工有哪些直接的下级
}

公司要来办party,你可以决定哪些员工来,哪些员工不来,规则:

1、 如果某个员工来了,那么这个员工的所有直接下级都不能来

2、 派对的整体快乐值是所有到场员工的快乐值的累加

3、 你的目标是让排队的整体快乐值尽量的大

给定一颗多叉树的头结点boss,请返回排队的最大快乐值

【分析】

①X不来:0+max{a来,a不来}+max{b来,b不来}+maxc来,c不来}(假设X有a,b,c三个直接下级)

②X来:X的快乐值+X某个子树整棵树的的最大快乐值

要求:头节点X来时的最大快乐值;头节点X不来时的最大快乐值

package tree;

import java.util.ArrayList;
import java.util.List;

public class MaxHappy {
	
	public static class Employee {
		public int happy;
		public List<Employee> nexts;

		public Employee(int h) {
			happy = h;
			nexts = new ArrayList<>();
		}

	}
	
	public static int maxHappy(Employee head) {
		Info allInfo = process(head);
		return Math.max(allInfo.no, allInfo.yes);
	}

	
	public static class Info {
		public int no;
		public int yes;

		public Info(int n, int y) {
			no = n;
			yes = y;
		}
	}
	
	public static Info process(Employee x) {
		if (x.nexts.isEmpty()) {
			return new Info(x.happy, 0);
		}
		int no = 0;
		int yes = x.happy;
		for (Employee next : x.nexts) {
			Info nextInfo = process(next);
			no += Math.max(nextInfo.no, nextInfo.yes);
			yes += nextInfo.no;

		}
		return new Info(no, yes);
	}
	
	
	
	public static void main(String[] args) {
		

	}

}

总结:

  1. 假设以X节点为头,假设可以向X左树和右树要任何信息
  2. 在上一步的假设下,讨论以X为头结点的树,得到答案的可能性(最重要),常见分类是与X无关的答案,与X有关的答案
  3. 列出所有可能性后,确定到底需要向左树和右树要什么样的信息
  4. 把左树信息和右树信息求全集,就是任何一颗子树都需要返回的信息S
  5. 递归函数都返回S,每颗子树都这么要求
  6. 写代码,在代码中考虑如何把左树信息和右树信息整合出整棵树的信息

源码:https://github.com/algorithmzuo/algorithmbasic2020

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值