每日一题:Leetcode-887 鸡蛋掉落

力扣题目

解题思路

java代码

力扣题目:

给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。

已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。

每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。

请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

 

示例 1:

输入:k = 1, n = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,肯定能得出 f = 0 。 
否则,鸡蛋从 2 楼掉落。如果它碎了,肯定能得出 f = 1 。 
如果它没碎,那么肯定能得出 f = 2 。 
因此,在最坏的情况下我们需要移动 2 次以确定 f 是多少。 

示例 2:

输入:k = 2, n = 6
输出:3

示例 3:

输入:k = 3, n = 14
输出:4

解题思路:

算法原理
这道题使用了动态规划和备忘录的方法来解决鸡蛋掉落的问题,以找到在给定鸡蛋数量和楼层数量的情况下,确定最少的尝试次数能保证找到鸡蛋恰好不碎的楼层。

思路

  1. 定义一个备忘录 memo 来存储已经计算过的结果,避免重复计算。
  2. dp 函数接受鸡蛋数量 k 和楼层数量 n 作为参数。
    • 如果楼层数为 0 ,返回 0 。
    • 如果只有 1 个鸡蛋,返回楼层数 n 。
    • 对于其他情况,通过二分搜索来确定一个尝试的楼层 x 。
    • 根据在 x 楼扔鸡蛋后的结果,更新搜索范围 lo 和 hi 。
    • 最终计算并返回最少的尝试次数,取在不同尝试楼层 lo 和 hi 下的最坏情况的最小值加 1 。

代码分析

  • 在 dp 函数中,首先检查备忘录中是否已经有计算结果,如果没有则进行计算并存储。
  • 二分搜索部分通过比较不同尝试楼层下碎与不碎的情况来调整搜索范围。

时间复杂度,其中 k 是鸡蛋数量,n 是楼层数量。
空间复杂度,用于存储备忘录中的结果。

java代码:

package com.example.lib;

import java.util.HashMap;
import java.util.Map;

public class Leetcode887 {
    public static void main(String[] args) {
        Leetcode887 leetcode887 = new Leetcode887();
        int ans = leetcode887.superEggDrop(2, 6);
        System.out.println(ans);
    }
    // 鸡蛋掉落
    Map<Integer, Integer> memo = new HashMap<Integer, Integer>();

    public int superEggDrop(int k, int n) {
        return dp(k, n);
    }

    public int dp(int k, int n) {
        if (!memo.containsKey(n * 100 + k)) {
            int ans;
            if (n == 0) {
                ans = 0;
            } else if (k == 1) {
                ans = n;
            } else {
                int lo = 1, hi = n;
                while (lo + 1 < hi) {
                    int x = (lo + hi) / 2;
                    int t1 = dp(k - 1, x - 1);
                    int t2 = dp(k, n - x);

                    if (t1 < t2) {
                        lo = x;
                    } else if (t1 > t2) {
                        hi = x;
                    } else {
                        lo = hi = x;
                    }
                }

                ans = 1 + Math.min(Math.max(dp(k - 1, lo - 1), dp(k, n - lo)), Math.max(dp(k - 1, hi - 1), dp(k, n - hi)));
            }

            memo.put(n * 100 + k, ans);
        }

        return memo.get(n * 100 + k);
    }
}

更多详细内容同步到公众号,感谢大家的支持!

每天都会给刷算法的小伙伴推送明日一题,并且没有任何收费项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L.2626

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值