树型动态规划,每次的主要步骤一样,利用递归实现。
一般遇到如下情形, 每次只需要获得左子树的信息和右子树的信息,再对得到的信息进行处理,周而复始这样的步骤,就可以使用树型动态规划模式实现功能。
满二叉树
二叉树,树的深度为k,节点个数为n,满足2^(k-1)==n,即为满二叉树
判断是否是满二叉树,可以利用它的特点,遍历出二叉树的深度和节点个数,是否满足公式即可。
得到左子树的深度和节点个数,得到右子树的深度和节点个数,对两个子树的深度和节点个数进行处理,得到当前树的深度和节点个数,周而复始,直到递归结束,即可得到树的深度和节点个数。
public static class ReturnData{
private int height;
private int nums;
public ReturnData(int height, int nums) {
this.height = height;
this.nums = nums;
}
}
private static boolean isFull(Node head){
if (null == head){
return true;
}
ReturnData res = process(head);
//这边需要注意,一定要加括号,位运算符<<优先级比-低
return (1<<res.height)-1 == res.nums;
}
private static ReturnData process(Node head){
if (null == head){
return new ReturnData(0, 0);
}
ReturnData leftData = process(head.left);
ReturnData rightData = process(head.right);
int height = Math.max(leftData.height,rightData.height) + 1;
int nums = leftData.nums + rightData.nums + 1;
return new ReturnData(height, nums);
}
完整测试代码
public class IsFullBinaryTree{
public static class Node{
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
}
public static class ReturnData{
private int height;
private int nums;
public ReturnData(int height, int nums) {
this.height = height;
this.nums = nums;
}
}
private static boolean isFull(Node head){
if (null == head){
return true;
}
ReturnData res = process(head);
return (1<<res.height)-1 == res.nums;
}
private static ReturnData process(Node head){
if (null == head){
return new ReturnData(0, 0);
}
ReturnData leftData = process(head.left);
ReturnData rightData = process(head.right);
int height = Math.max(leftData.height,rightData.height) + 1;
int nums = leftData.nums + rightData.nums + 1;
return new ReturnData(height, nums);
}
public static void main(String[] args) {
Node node = new Node(1);
node.left = new Node(2);
node.right = new Node(3);
node.left.left = new Node(4);
node.left.right = new Node(5);
node.right.left = new Node(6);
node.right.right = new Node(7);
node.left.left.left = new Node(8);
// node.left.left.right = new Node(9);
boolean full = isFull(node);
System.out.println(full);
}
}
平衡二叉树
平衡二叉树,任一左右子树的高度差不超过1的二叉树
【思路】
得到左子树的高度,是否是平衡二叉树,得到右子树的高度,是否是平衡二叉树,综合处理左右两棵子树,判断两棵是否是平衡二叉树,是的话,继续判断2棵子树的高度差是都小于1,周而复始,直至递归结束
public static class ReturnData{
private int height;
private boolean isBBT;
private ReturnData(int height, boolean isBBT) {
this.height = height;
this.isBBT = isBBT;
}
}
private static boolean ifBalancedTree(Node head){
if (null == head){
return true;
}
ReturnData result = process(head);
return result.isBBT;
}
private static ReturnData process(Node head){
if (null == head){
return new ReturnData(0, true);
}
ReturnData leftData = process(head.left);
ReturnData rightData = process(head.right);
int height = Math.max(leftData.height, rightData.height);
int diff = Math.abs(leftData.height-rightData.height);
boolean isBBT = true;
if (!leftData.isBBT || !rightData.isBBT || diff >1){
isBBT = false;
}
return new ReturnData(height, isBBT);
}
完整测试代码
public class IfBalancedTree{
public static class Node{
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
}
public static class ReturnData{
private int height;
private boolean isBBT;
private ReturnData(int height, boolean isBBT) {
this.height = height;
this.isBBT = isBBT;
}
}
private static boolean ifBalancedTree(Node head){
if (null == head){
return true;
}
ReturnData result = process(head);
return result.isBBT;
}
private static ReturnData process(Node head){
if (null == head){
return new ReturnData(0, true);
}
ReturnData leftData = process(head.left);
ReturnData rightData = process(head.right);
int height = Math.max(leftData.height, rightData.height) + 1;
int diff = Math.abs(leftData.height-rightData.height);
boolean isBBT = true;
if (!leftData.isBBT || !rightData.isBBT || diff >1){
isBBT = false;
}
return new ReturnData(height, isBBT);
}
public static void main(String[] args) {
Node node = new Node(1);
node.left = new Node(2);
node.right = new Node(3);
node.left.left = new Node(4);
node.left.right = new Node(5);
node.right.left = new Node(6);
node.right.right = new Node(7);
node.left.left.left = new Node(8);
// node.left.left.left.left = new Node(9);
boolean balancedTree = ifBalancedTree(node);
System.out.println(balancedTree);
}
}
搜索二叉树
搜索二叉树,左子树的最大值小于父节点,右子树的最小值大于父节点
【思路】
同样的步骤,获得左子树是否是搜索二叉树,左子树的最大值,获得右子树是否是搜索二叉树,右子树的最小值,如果左子树是搜索二叉树,右子树也是搜索二叉树,同时满足,左子树的最大值<当前节点的值,右子树的最小值>当前节点的值,满足条件则表示当前树是搜索二叉树,重复这样的步骤,直到递归结束
public class IsBST {
public static class Node{
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
}
public static class ReturnData{
private boolean isBST;
private int min;
private int max;
public ReturnData(boolean isBST, int min, int max) {
this.isBST = isBST;
this.min = min;
this.max = max;
}
@Override
public String toString() {
return "ReturnData{" +
"isBST=" + isBST +
", min=" + min +
", max=" + max +
'}';
}
}
//经典套路
/**
* 左树是否是搜索二叉树
* 右树是否是搜索二叉树
* 左树的最大值是否小于当前节点
* 右树的最小值是否大于当前节点
* @param head
* @return
*/
private static boolean checkBST4(Node head){
ReturnData returnData = process2(head);
System.out.println(returnData);
return returnData.isBST;
}
private static ReturnData process2(Node head){
if (null == head){
return null;//
}
ReturnData leftData = process2(head.left);
ReturnData rightData = process2(head.right);
boolean isBST = true;
int min = head.value;
int max = head.value;
if (null != leftData){
min = Math.min(min, leftData.min);
max = Math.max(max, leftData.max);
}
if (null != rightData){
min = Math.min(min, rightData.min);
max = Math.max(max, rightData.max);
}
if (null != leftData && (!leftData.isBST || leftData.max >= head.value)){
isBST = false;
}
if(null != rightData && (!rightData.isBST || rightData.min <= head.value)){
isBST = false;
}
// 两种判断方式都可以
// boolean isBST = false;
// if (
// (null != leftData ? (leftData.isBST && leftData.max < head.value) : true)
// &&
// (null != rightData ? (rightData.isBST && rightData.min > head.value) : true)
// ){
// isBST = true;
// }
return new ReturnData(isBST, min, max);
}
public static void main(String[] args) {
Node node = new Node(5);
node.left = new Node(3);
node.left.left = new Node(1);
node.left.right = new Node(4);
node.right = new Node(7);
node.right.left = new Node(6);
node.right.right = new Node(8);
boolean bst4 = checkBST4(node);
System.out.println(bst4);
}
}
树型动态规划,每次的主要步骤一样,利用递归实现。
一般遇到如下情形, 每次只需要获得左子树的信息和右子树的信息,再对得到的信息进行处理,周而复始这样的步骤,就可以使用树型动态规划模式实现功能。
不是所有的二叉树题型都可以用这种方式实现,需要具体情况具体讨论,符合条件的才可以,比如说判断是否是完全二叉树则不可以按照这样的模式实现
关于树型动态规划的代码都是根据左程云老师的算法课程整理出来的