跳至主要內容

LCS 01. 下载插件

daipeng大约 3 分钟

小扣打算给自己的 VS code 安装使用插件,初始状态下带宽每分钟可以完成 1 个插件的下载。假定每分钟选择以下两种策略之一:

使用当前带宽下载插件
将带宽加倍(下载插件数量随之加倍)
请返回小扣完成下载 n 个插件最少需要多少分钟。

注意:实际的下载的插件数量可以超过 n 个

示例 1:

输入:n = 2

输出:2

解释:
以下两个方案,都能实现 2 分钟内下载 2 个插件

方案一:第一分钟带宽加倍,带宽可每分钟下载 2 个插件;第二分钟下载 2 个插件
方案二:第一分钟下载 1 个插件,第二分钟下载 1 个插件
示例 2:

输入:n = 4

输出:3

解释:
最少需要 3 分钟可完成 4 个插件的下载,以下是其中一种方案:
第一分钟带宽加倍,带宽可每分钟下载 2 个插件;
第二分钟下载 2 个插件;
第三分钟下载 2 个插件。

提示:

1 <= n <= 10^5

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/Ju9Xwi
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

实际上这道题是一个两个变量的二元一次方程,类似于n 刚好小于等于 f(g(x),y),g(x)表示x次增加带宽后得到的每次下载数量,f(g(x),y)则表示在g(x)的下载带宽下,继续下载y次可以刚好大于等于n。现在要求y+x的最小值。 x和y是互相影响的,增大越多次带宽,那么下载分钟数是越少的,而两者之和则并不确定,故需要枚举所有的和来找到最小值。 我们可以按照增加带宽次数来计算,初始时带宽为1,我们同时记带宽增加次数为0,然后将带宽翻倍,同时带宽增加次数加1,这样可以得到一个总次数值,我们持续遍历,找到最小的总次数值即可。

 public int leastMinutes(int n) {
        int min = Integer.MAX_VALUE;
        int initial = 1; //初始带宽
        int inc = 0; //带宽增加次数
        while(initial  <= n ){
            if((n % initial) == 0){
                int cur = n / initial + inc;//假如initial可以整除n,那么所需次数就是自增到带宽的次数+在该带宽条件下所需的下载次数(每分钟算一次)
                if(cur < min){
                    min = cur;
                }
            }else{
                int cur = n / initial + 1 + inc;//假如initial不可以整除n,那么所需次数就是自增到带宽的次数+在该带宽条件下所需的下载次数(每分钟算一次)+ 1
                if(cur < min){
                    min = cur;
                }
            }
            initial = 2 * initial;//带宽翻倍
            inc++;//带宽增加次数自增
        }
        return min;
    }

上述代码可以简化:

 public int leastMinutes(int n) {
        int min = Integer.MAX_VALUE;
        int initial = 1; //初始带宽
        int inc = 0; //带宽增加次数
        int cur  = 0;
        while(initial  <= n ){
            if((n % initial) == 0){
                cur = n / initial + inc;//假如initial可以整除n,那么所需次数就是自增到带宽的次数+在该带宽条件下所需的下载次数(每分钟算一次)
            }else{
                cur = n / initial + 1 + inc;//假如initial不可以整除n,那么所需次数就是自增到带宽的次数+在该带宽条件下所需的下载次数(每分钟算一次)+ 1
            }
            if(cur < min){
                min = cur;
            }
            initial = 2 * initial;//带宽翻倍
            inc++;//带宽增加次数自增
        }
        return min;
    }

该题是蓄水一题的简化版本。