Leetcode 1552. Magnetic Force Between Two Balls 二分法的神仙操作以及在大佬提示下的二分万能套路

新套路

  • 不建议最后返回l或者r,反而思路不够清晰
    框架
  • 让ans记录上一次符合check要求的mid,剩下什么都不用管了
while(l<=r){
	m=l+(r-l)/2
	if check1(m)
		update ans
		l=mid+1
	else if check2(m)
		update ans
		r=mid-1
	else ...可能有三种情况
}
return ans
class Solution {
public:
    int maxDistance(vector<int>& position, int m) {
        len = position.size();
        sort(position.begin(), position.end());
        int l=0, r=position[len-1]-position[0];
        int ans=0;
        while(l<=r){
            int mid = l+(r-l)/2;
            if(count(mid, position)>=m){
                ans=mid;
                l=mid+1;
            }
            else if(count(mid, position)<m){
                r=mid-1;
            }
        }
        return ans;
    }
private:
    int len;
    int count(int d, vector<int>& position){
        int ans=1;
        int cur=position[0];
        for(int i=1; i<len; i++){
            if(position[i]-cur>=d){
                cur=position[i];
                ans++;
            }
        }
        return ans;
    }
};

原套路

参考

  • 问题转换一下

    • 用count(d)表示:当最小的距离是d时,最多能够放的球的个数,目标就是去找count(d)==m时,最大的d
    • 用二分思想:
      • 当count(d)
      • 当count(d)>m时,说明d太小了,还有更多的球能放
    • 但是,要注意这个问题不是去找满足count(d)==m 的d,因为可能有很多种比如[1,2,3,4,5,999999]中,只要d>5,就都满足m==2,我们的目标是找到这其中最大的d
  • 最需要记住的套路

  • 一般二分法

    • mid = l+(r-l)/2 , l = mid+1, r=mid-1
    • 它的问题是,如果l=0 r=1那么会陷入死循环,一般的查找问题用它就够了
  • 解决这个问题的套路有两种:

    • m = l + (r-l)/2 with l = m + 1 and r = m
    • m = r - (r-l)/2 with l = m and r = m - 1
    • 这样的就能解决如(0,1)中,我想要mid=1跳出循环的需求
class Solution {
public:
    int maxDistance(vector<int>& position, int m) {
        len = position.size();
        sort(position.begin(), position.end());
        int l=0, r=position[len-1]-position[0];
        while(l<r){
            int mid = r-(r-l)/2;
            if(count(mid, position)>=m)
                l=mid;
            else if(count(mid, position)<m){
                r=mid-1;
            }
        }
        return l;
    }
private:
    int len;
    int count(int d, vector<int>& position){
        int ans=1;
        int cur=position[0];
        for(int i=1; i<len; i++){
            if(position[i]-cur>=d){
                cur=position[i];
                ans++;
            }
        }
        return ans;
    }
};

你可能感兴趣的:(算法)