算法进阶面试题05——树形dp解决步骤、返回最大搜索二叉子树的大小、二叉树最远两节点的距离、晚会最大活跃度、手撕缓存结构LRU

本文介绍了如何使用树形动态规划(DP)解决算法面试中的典型问题,包括:如何找到最大搜索二叉子树的大小、计算二叉树中最远两节点的距离、以及在晚会最大活跃度场景下优化员工邀请策略。文章通过分析可能性、收集信息和改递归步骤详细阐述了解题思路,并提到了LRU缓存结构的设计问题。
摘要由CSDN通过智能技术生成

第一题:

给定一棵二叉树的头节点head,请返回最大搜索二叉子树的大小

 

二叉树的套路

统一处理逻辑:假设以每个节点为头的这棵树,他的最大搜索二叉子树是什么。答案一定在其中

 

第一步,列出可能性(最难部分)

1、可能来自左子树上的某课子树

2、可能来自右子树上的某课子树

3、整颗都是(左右子树都是搜索二叉树并且左子树最大小于该节点,右子树最小大于该节点)

 

 

 

第二步,收集信息:

1、左树最大搜索子树大小

2、右树最大搜索子树大小

3、左树最大二叉搜索子树的头部(通过查看这个头部是否等于节点的左孩子,来判断整个左子树是否都是二叉搜索树)

4、右树最大二叉搜索子树的头部

5、左树最大值

6、右树最小值

 

 

化简为一个信息体:

1、左/右搜大小

2、左/右搜头

3、左max

4、右min

 

不管左树还是右树都存储

1、最大搜索子树大小

2、最大搜索子树的头部

3、这棵树上的最大值和最小值

 

如果不理解可以看引子题(很简单的)

一棵树中找最大最小

 

 

 

 

第三步,改递归(比较复杂)

先假设左和右都给我这样的信息了,然后怎么利用左边和右边的信息,组出来我该返回的信息。最后baseKey填什么,搞定!

 

复制代码

public class Code_04_BiggestSubBSTInTree {

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

        public Node(int data) {
            this.value = data;
        }
    }

    public static Node biggestSubBST(Node head) {
        int[] record = new int[3]; // 0->size, 1->min, 2->max
        return posOrder(head, record);
    }
    
    public static class ReturnType{
        public int size;
        public Node head;
        public int min;
        public int max;
        
        public ReturnType(int a, Node b,int c,int d) {
            this.size =a;
            this.head = b;
            this.min = c;
            this.max = d;
        }
    }
    
    public static ReturnType process(Node head) {
        if(head == null) {
            //设置系统最大最小为了不干扰判断最大最小的决策
            return new ReturnType(0,null,Integer.MAX_VALUE, Integer.MIN_VALUE);
        }
        Node left = head.left;
        ReturnType leftSubTressInfo = process(left);//当成一个黑盒
        Node right = head.right;
        ReturnType rightSubTressInfo = process(right);
        
        int includeItSelf = 0;
        if(leftSubTressInfo.head == left 
                &&rightSubTressInfo.head == right
                && head.value > leftSubTressInfo.max
                && head.value < rightSubTressInfo.min
                ) {
            includeItSelf = leftSubTressInfo.size + 1 + rightSubTressInfo.size;
        }
        int p1 = leftSubTressInfo.size;
        int p2 = rightSubTressInfo.size;
        //解黑盒的过程
        int maxSize = Math.max(Math.max(p1, p2), includeItSelf);

        Node maxHead = p1 > p2 ? leftSubTressInfo.head : rightSubTressInfo.head;
        if(maxSize == includeItSelf) {
            maxHead = head;
        }
        
        return new ReturnType(maxSize,
                maxHead, 
                Math.min(Math.min(leftSubTressInfo.min,rightSubTressInfo.min),head.value),
                Math.max(Math.max(leftSubTressInfo.max,rightSubTressInfo.max),head.value));    
    }

    //数组实现版本
    public static Node posOrder(Node head, int[] record) {
        if (head == null) {
            record[0] = 0;
            record[1] = Integer.MAX_VALUE;
            record[2] = Integer.MIN_VALUE;
            return null;
        }
        int value = head.value;
        Node left = head.left;
        Node right = head.right;
        Node lBST = posOrder(left, record);
        int lSize = record[0];
        int lMin = record[1];
        int lMax = record[2];
        Node rBST = posOrder(right, record);
        int rSize = record[0];
        int rMin = record[1];
        int rMax = record[2];
        record[1] = Math.min(rMin, Math.min(lMin, value)); // lmin, value, rmin -> min 
        record[2] =  Math.max(lMax, Math.max(rMax, value)); // lmax, value, rmax -> max
        if (left == lBST && right 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值