力扣算法学习day37-2+3-周赛后两道

力扣算法学习day37-2+3-周赛后两道

6010-完成旅途的最少时间

题目

image-20220227162028036

image-20220227162054405

代码实现

class Solution {
    public long minimumTime(int[] time, int totalTrips) {
        // 二分查找
        Arrays.sort(time);
        // right为最大时间
        long right = 1L * totalTrips * time[0];
        long left = 0;

        while(left < right){
            long mid = (left + right) / 2;
            long trips = 0;

            for(int i : time){
                if(mid < i){
                    break;
                }
                trips += mid / i;
            }

            // 只让left想右移动,trips包含等于totalTrips,保证最后结果是最小的等于totalTrips的数。
            if(trips >= totalTrips){
                right = mid;
            } else{
                left = mid + 1;
            }
        }
        

        return left;
    }
}

6011-完成比赛时间的最少时间

题目

image-20220227221905283

image-20220227221926492

image-20220227221953872

class Solution {
    public int minimumFinishTime(int[][] tires, int changeTime, int numLaps) {
        // 思路看了灵神的思路。具体为什么minSec数组为什么取长度17,可以直接在题解看,主要是灵神直接给的代码
        // 还是不是很容易看懂,所以自己做了些注释,方便自己查询和他人也可以看看。

        // (1) 按照上面分析,需要先求用一个轮胎跑i圈用时最少多少。用数组minSec[i]表示。

        // minSec[i]代表用一个轮胎,跑i圈,所用的最少时间,因为只需要知道最小时间,而不需要知道是哪个轮胎跑的。    
        // 注:minSec[0]没有用,这样minSec[i]的意义更协调,即用一个轮胎跑i圈用的最少时间。
        int[] minSec = new int[18];

        // 注:填充数组每个值为Integer.MAX_VALUE / 2 是为了防止(2)中dp的状态转移方程 f[i - j] + minSec[j] 溢出
        Arrays.fill(minSec, Integer.MAX_VALUE / 2);

        // 枚举每一个轮胎,跑i圈的最小值,然后取跑i圈的最小值。
        for (int[] tire : tires) {
            int time = tire[0];

            // 1.sum大于changeTime + tire[0]  说明换这个轮胎的新轮胎来跑的时间会更短,则
            //   可以退出循环了,单个轮胎已经到了能够跑的圈数的极限了。
            // 2.i需要小于numLaps是因为题目的圈数是numLaps,那么我们需要求的minSec[i]不需要更大的了。
            for (int i = 1, sum = 0; sum <= changeTime + tire[0] && i <= numLaps; i++) {
                // 单个轮胎跑i圈的时间迭代。
                sum += time;

                // 与所有轮胎同i圈 进行比较,取跑i圈时的最小时间。
                minSec[i] = Math.min(minSec[i], sum);

                // 按照题意,每跑完一圈后,同一个轮胎下一圈消耗的时间会呈指数倍增长.
                time *= tire[1];
            }
        }



        // (2) 求得了同一个轮胎跑i圈时的最小时间后,可以求得跑i圈的最短时间。
        // 状态传递比较简单,主要注释一下minSec的情况。下面遍历取最小对于出现有单个轮胎跑不到17圈的情况会有影响吗?
        // 假设有效的minSec是最多单个跑13圈,那么13圈后都是 Integer.MAX_VALUE / 2,那么先看看条件限制,
        // 1 <= fi, changeTime <= 10的5次方,2 <= ri <= 10的5次方,1 <= numLaps <= 1000,所以所用
        // 最大时间最大是10的8次方的数量级,远小于Integer.MAX_VALUE / 2,那么在Math.min(dp[i], dp[i - j] + minSec[j])
        // 公式中无效的minSec其实就不会取的,一定会被覆盖,所以没有影响。
        int[] dp = new int[numLaps + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;

        // dp[i]表示跑i圈,所用的最少时间
        for (int i = 1; i <= numLaps; i++) {

            // 1.最后j圈由一个轮胎跑,可以得到dp[i] = dp[i - j] + minSec[j],然后j遍历取dp[i]最小。
            // 2.每次换轮胎都需要加上changeTime,因为结构原因,所以包括第一个也加上了。
            for (int j = 1; j <= Math.min(17, i); j++){
                dp[i] = Math.min(dp[i], dp[i - j] + minSec[j]);
            }
            
            // 每一圈都
            dp[i] += changeTime;
        }

        // 减去多算了的一次换胎过程(第一次不需要换胎)
        return dp[numLaps] - changeTime;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

人山人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值