LeetCode 二分算法 范围内整数的最大得分
范围内整数的最大得分
给你一个整数数组 start 和一个整数 d,代表 n 个区间 [start[i], start[i] + d]。
你需要选择 n 个整数,其中第 i 个整数必须属于第 i 个区间。所选整数的 得分 定义为所选整数两两之间的 最小 绝对差。
返回所选整数的 最大可能得分 。
示例 1:
输入: start = [6,0,3], d = 2
输出: 4
解释:
可以选择整数 8, 0 和 4 获得最大可能得分,得分为 min(|8 - 0|, |8 - 4|, |0 - 4|),等于 4。
示例 2:
输入: start = [2,6,13,13], d = 5
输出: 5
解释:
可以选择整数 2, 7, 13 和 18 获得最大可能得分,得分为 min(|2 - 7|, |2 - 13|, |2 - 18|, |7 - 13|, |7 - 18|, |13 - 18|),等于 5。
提示:
2 <= start.length <= 105
0 <= start[i] <= 109
0 <= d <= 109
题解
我们可以看到,题目要求得分的最大值
而得分是所有两数差的最小值
也就是最小值的最大值,所以我们对得分采用二分算法,二分得到最大的得分
首先确定二分的边界,也就是得分的边界
最小值是 0 ,因为绝对值大于等于0
最大值是数组 start 中的最大值 + d
接着,对于一个得分 m ,我们要如何进行二分
- 假设一个当前某一个区间的数为 x0
- 要使得分为 m ,则下一个数 x1至少为 x0 + m
- 假如 x0 + m 在下一个数的区间[ x1 , x1+d ]内,则此区间内的数取为 x0 + m
- else if x0 + m > x1 + d 说明不可能让得分为 m ,需要将右边界置为 m-1
- else if x0 + m < x1 则下一个区间的数取为 x1
- 如果数组 start 中的所有数据都可以得到得分 m
- 那么 m就是一个可能的值,记录下来,将左边界置为m+1
上述步骤中,对于下一个数的取值,永远是大于等于前一个数,这样就可以避免绝对值的两端讨论
但是要使这样的操作是正确的,前提是数组中的数据是升序的,这样下一个数的取值才是永远大于前一个数的
所以首先对数组 start 进行排序
对于第一个数 x0 的取值,因为要获得m得分,下一个数的取值要 >= x0+m,所以 x0 越小,下一个数的取值就越有可能满足条件,所以 x0 就是 strat[ 0 ]
代码如下↓
int maxPossibleScore(int* start, int startSize, int d) {int cmp(void const* a,void const* b){return *(int*)a - *(int*)b;}qsort(start,startSize,sizeof(int),cmp);long long l=0,r=start[startSize-1]+d;int res=0;while(l<=r){long long m=(l+r)/2;long long x=start[0];int f=1;for(int i=1;i<startSize;i++){x+=m;if(x>start[i]+d){r=m-1;f=0;break;}else{if(x<start[i]){x=start[i];}}}if(f){res=m;l=m+1;}}return res;
}