记录一道经典的二分题- Leetcode 1552. 两球之间的磁力

题目描述:

对于这种 最大化的最小 或是 最小化的最大  题目 —— 都可以采用二分的算法来解决
(因为以最大化的最小为例 若ans = x,则对于其他的情况一定都小于x,若有其他的情况能产生使ans > x的则说明x不满足要求)

相当于告诉你了一个答案的区间,每次对中间的数去尝试解决问题,若能解决则左边界右移,若不能右边界左移(另一种情况同理)


所以可以采用对答案所在的区间进行二分来解决

以本题为例:
首先分析 ans 的l,r分别为多少 
在那么多个位置中加入m个小球,r = (max-min)/m, l = min(d1,d2,...,dn-1) 【n-1段距离的最小值】
然后对于每一个mid进行check处理,看是否能有这种情况,若不存在,说明mid太大了,所以 r = mid-1; 若存在则 l = mid+1;
最终返回 max(l,r)-1 即可

" 对于check() 可以用贪心来解决——从position[0]开始安置小球,然后下一个安置小球的为位置是上一个位置大ans的第一个位置

 若能成功安置全部的小球则返回true,否则返回false "


   boolean check(int[] position, int distance, int m) {
        int count = 1;
        int i = 0;
        for (int j = 1; j < position.length; j++) {
            if (position[j] - position[i] >= distance) {
                i = j;
                count++;
                if (count >= m) return true;
            }
        }
        return false;
    }

二分的算法:

    int maxDistance(vector<int>& position, int m) {
        if(m > position.size()) return 0;
        sort(position.begin(),position.end());
        int r = (position[position.size()-1]-position[0])/(m-1);
        int l = 0;
        for(int i =1;i<position.size();i++)
            l = min(l,position[i]-position[i-1]);
        // cout<<l<<" "<<r<<endl;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(check(position,mid,m)) l = mid+1;
            else r = mid -1;
        }
        return max(l,r)-1;
    }

相似题目:778. 水位上升的泳池中游泳

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值