leetcode周赛1552. 两球之间的磁力-自己做总结出的注意点

leetcode周赛1552. 两球之间的磁力


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

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

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


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

二分查找

leetcode上面有很多类似的(比如1482和lcp那个小张做题),这种题的特点是问最小的最大或者最大的最小。都是通过一个能取到的最大值开始二分,直至不满足条件。
拿本题来说,磁力的最大值是position的最后一个减掉第一个(其实除以球的个数会进一步缩小范围)。从这个最大值开始二分,查出来最后的答案,每次用当前的磁力值判断能不能构成这样的一种情况。比如说我们有三个球,position[1,5,10],假设当前算的磁力是4,check要判断这是不满足要求的。
check结束了,说一下左右边界的变化范围。因为是寻找最大化的,所以当存在一个满足条件后,需要让 left=mid+1 ,不存在令 right = mid - 1

错误理解check

我们用一个check方法来检验当前磁力能否满足条件。
先看我的错误思路。
用hashmap存储position,key为position,value为1。check会检查是否存在一个数组的序列,其中任意一个数a,存在b,满足 a+distance==b

private boolean check(HashMap<Integer,Integer> map,int distance,int m) {
        int flag = 0;
        Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer,Integer> entry = iterator.next();
            flag = 1;
            int prev = entry.getKey();
            while (true) {
                int n = prev + distance;
                if (map.containsKey(n)) {
                    flag++;
                    prev = n;
                } else {
                    break;
                }
                if (flag == m) {
                    return true;
                }
            }
        }
        return false;
    }

这么做就错在等于上,因为我们是二分答案,可能不会直接存在这么一组样例满足恰好等于间隔的情况,这样就会由于二分的判定条件,令right=mid-1,从而错过正确答案(第二个样例就是)。正确的情况应该是存在两个数 a-b>=distance

正确代码

class Solution {
    public int maxDistance(int[] position, int m) {
        Arrays.sort(position);
        int len = position.length;
        int left = 0,right = position[len - 1] - position[0];
        int mid = 0;
        while (left <= right) {
            mid = (left + right) >>> 1;
            boolean flag = check(position,mid,m);
            if (flag) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left - 1;
    }
    //判断distance下整个数组是否存在满足条件的
    //大于等于就行,不能严格等于
    private boolean check(int[] arr,int distance,int m) {
        int count = 0;
        int i = 0;
        for (int j = 1; j < arr.length; j++) {
            if (arr[j] - arr[i] >= distance) {
                count++;
                if (m - 1== count) {
                    return true;
                }
                i = j;
            }
        }
        return false;
    }
}

leetcode 119

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值