竞赛202

1552. 两球之间的磁力

 

在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。

已知两个球如果分别位于 x 和 y ,那么它们之间的磁力为 |x - y| 。

给你一个整数数组 position 和一个整数 m ,请你返回最大化的最小磁力。

 

示例 1:

 

输入:position = [1,2,3,4,7], m = 3
输出:3
解释:将 3 个球分别放入位于 1,4 和 7 的三个篮子,两球间的磁力分别为 [3, 3, 6]。最小磁力为 3 。我们没办法让最小磁力大于 3 。
示例 2:

输入:position = [5,4,3,2,1,1000000000], m = 2
输出:999999999
解释:我们使用位于 1 和 1000000000 的篮子时最小磁力最大。
 

提示:

n == position.length
2 <= n <= 10^5
1 <= position[i] <= 10^9
所有 position 中的整数 互不相同 。
2 <= m <= position.length

/**
 * @param {number[]} position
 * @param {number} m
 * @return {number}
 */
var maxDistance = function(position, m) {
    position.sort((a, b)=>a-b);
    let len = position.length;
    // 2个球任意距离的最小值
    let r = Math.floor((position[len-1]-position[0])/(m-1));
    let l = 1;
    const check = (mid)=>{
        let count =1; // 0点位置放一个球
        let j = 0;
        for(let i=1; i<len; i++){
            if(position[i]-position[j] >=mid){
                count++;
                j=i;
                if(count>=m) return true
            }
        }
        return false
    }
    let res;
    while(l<=r){
        let mid = Math.floor((l+r)/2);
        // 是否能达到 mid 距离
        if(check(mid)){
            res = mid;
            l = mid+1;
        } else {
            r = mid-1;
        }
    }
    return res;
};

 

 

思考:这个当时,我也想到二分法,并且感觉二分可以解决的,把索引二分(当时想到了),索引对应的值二分(当时想到了),但是就不知道怎么处理了,当时还一直有个想法就是遍历点注定会超时,这个想法导致自己不想去循环这个数组。

位置排序后根据初始和结束 ,以及球的个数是可以知道最大化距离的,但所给的点不一定满足要求,(当时想到了)

步骤一:把最大距离“二分法”,看所给的点满足要求吗?l=1, r = max,mid = Math.floor((l+r)/2), 遍历所给的点看是否能达到mid。

步骤二:l = mid+1, r=  max 或 l= 1, r = mid-1, ,mid = Math.floor((l+r)/2), 遍历所给的点看是否能达到mid。

重复(步骤二)这个过程。

 关于“二分法” 为什么会出现 mid+1 或 mid-1

 

 l=97 => 98, 如果此时 98 没有 +1, 那么 l=98, =>min =98 => 又赋值给l =98 =>死循环,所以 必须有 l = mid+1 => l= 98+1

最终的判断条件 l<=r, 最后满足的条件是左边 = 右边。

 

1553. 吃掉 N 个橘子的最少天数

厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子:

吃掉一个橘子。
如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。
如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。
每天你只能从以上 3 种方案中选择一种方案。

请你返回吃掉所有 n 个橘子的最少天数。

 

示例 1:

输入:n = 10
输出:4
解释:你总共有 10 个橘子。
第 1 天:吃 1 个橘子,剩余橘子数 10 - 1 = 9。
第 2 天:吃 6 个橘子,剩余橘子数 9 - 2*(9/3) = 9 - 6 = 3。(9 可以被 3 整除)
第 3 天:吃 2 个橘子,剩余橘子数 3 - 2*(3/3) = 3 - 2 = 1。
第 4 天:吃掉最后 1 个橘子,剩余橘子数 1 - 1 = 0。
你需要至少 4 天吃掉 10 个橘子。
示例 2:

输入:n = 6
输出:3
解释:你总共有 6 个橘子。
第 1 天:吃 3 个橘子,剩余橘子数 6 - 6/2 = 6 - 3 = 3。(6 可以被 2 整除)
第 2 天:吃 2 个橘子,剩余橘子数 3 - 2*(3/3) = 3 - 2 = 1。(3 可以被 3 整除)
第 3 天:吃掉剩余 1 个橘子,剩余橘子数 1 - 1 = 0。
你至少需要 3 天吃掉 6 个橘子。
示例 3:

输入:n = 1
输出:1
示例 4:

输入:n = 56
输出:6
 

提示:

1 <= n <= 2*10^9

 

// 这个是超时的
/**
 * @param {number} n
 * @return {number}
 */
var minDays = function(n) {
    // 吃 n 个橘子 最少天数是 d[n]
    let dp = new Array(n+1).fill(0);
    dp[1] = 1;
    dp[2] = 2; 
    for(let i=3; i<=n; i++){
        let m1 = Infinity, m2 = Infinity, m3 = Infinity;
        // 必须加 ()
        if(!(i%2)){
            m1 = dp[i/2]+1
        }
        if(!(i%3)){
            m2 = dp[i/3]+1
        }
        m3 = dp[i-1]+1
        dp[i] = Math.min(m1, m2, m3)
    }
    return dp[n]
};

 

 

思考: 记得当时,想着用dp,然后还递归 getCount(n-1), 根据往常经验还循环了一下,n是橘子,最初始的条件是, n=1时,返回1,不知道改怎么去dp这道题。

还是没梳理清楚关系,dp[i] 代码 i 个橘子最少吃 dp[i] 天

 
var minDays = function(n) {
    let d = [];
    const dfs = (n, d)=>{
        if(n===1) return 1;
        if(n===2) return 2;
        if(d[n]) return d[n];
        let ans = Infinity;
        ans = Math.min(ans, n % 2 + dfs(Math.floor(n/2),d)+1)
        ans = Math.min(ans, n % 3 + dfs(Math.floor(n/3),d)+1)
        return d[n] = ans
    }
    return dfs(n, d)
}

 

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/magnetic-force-between-two-balls
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

 

 

 

 

 

 

 

 

posted @ 2020-08-17 11:07  土豆zhang  阅读(129)  评论(0编辑  收藏  举报