2. LeeCode 高楼抛鸡蛋(进阶算法---二分搜索优化法)

基础解法前面写过,链接如下:
Leecode高楼抛鸡蛋 --递归回溯法和动态规划法
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码如下
class ThrowEgg {
    int[][] memo;
    // int count;

    public static void main(String[] args) {
        ThrowEgg te = new ThrowEgg();
        // System.out.println(ta.innerLoop(1, 2));
        System.out.println(te.outerLoop(2, 6));
        // System.out.println(te.outerLoop(3, 14));
        // System.out.println(te.count);
    }

    public int outerLoop(int k, int n) {
        memo = new int[k + 1][n + 1];
        return innerLoop(k, n);
    }

    // 用二分搜索查找谷底。
    public int innerLoop(int k, int n) {

        if (k == 1) return n;
        if (n == 0) return 0;

        if (memo[k][n] != 0) return memo[k][n];

        int res = Integer.MAX_VALUE;
        int le = 1, ri = n;

        while (le <= ri) {
            int mid = (le + ri) / 2;
            int broken = innerLoop(k - 1, mid - 1); //碎
            int non_broken = innerLoop(k, n - mid); //不碎
            // res = (碎,没碎)+1,加1是因为不管碎没碎,我都抛了一次
            // 谁大谁 +1的原因是因为要找 剩余楼层最多的那个。(保证最坏情况)
            if (broken > non_broken) {
                ri = mid - 1;  //这个和递归树无关,和那张单调图有关
                res = Math.min(res, broken + 1);
            } else {
                le = mid + 1;  //这个和递归树无关,和那张单调图有关
                res = Math.min(res, non_broken + 1);
            }
            // count++;
        }
        memo[k][n] = res;
        return res;
    }

}
代码解释

这个解法其实是两个部分的耦合,应该把这两部分分开来思考。否则容易两部分交叉,给思考增加难度

分成了这两部分:
1.递归树(目的是解决min(max))
2.单调图(目的是解决先从第几楼开始抛)

第一部分需要的元素:
k鸡蛋数,
n最高楼层,
mid:从第mid层抛鸡蛋。
递归树元素(k,n):最高层是n,有k个鸡蛋,找出f的最小次数

第二部分需要的元素:le,ri,mid

两者共有的元素 broken non_broken

递归树部分就不分析了,看下面的图自己理解。
在这里插入图片描述

分析一下第二部分
只看第一层,
一开始le =1 , ri=6 所以mid=3,此时broken<non_broken,即黄线>蓝线,此时把le=mid+1
然后到了 le = 4, ri=6 ,所以mid=5,此时non_broken>broken,即蓝线>黄线,还是没有重合。那么再度逼近。
总结:变更le 和 ri的根本目的是让横坐标朝交叉点的横坐标无线接近
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值