题目链接
题目描述
给你三个正整数 n、index 和 maxSum 。你需要构造一个同时满足下述所有条件的数组 nums(下标 从 0 开始 计数):
- n u m s . l e n g t h = = n nums.length == n nums.length==n
- nums[i] 是 正整数 ,其中 0 <= i < n
- a b s ( n u m s [ i ] − n u m s [ i + 1 ] ) < = 1 abs(nums[i] - nums[i+1]) <= 1 abs(nums[i]−nums[i+1])<=1 ,其中 0 < = i < n − 1 0 <= i < n-1 0<=i<n−1
- nums 中所有元素之和不超过 maxSum
- nums[index] 的值被 最大化
返回你所构造的数组中的 nums[index] 。
示例 1:
输入:n = 4, index = 2, maxSum = 6
输出:2
解释:数组 [1,1,2,1] 和 [1,2,2,1]
满足所有条件。不存在其他在指定下标处具有更大值的有效数组。
示例 2:
输入:n = 6, index = 1, maxSum = 10
输出:3
提示:
1 < = n < = m a x S u m < = 1 0 9 1 <= n <= maxSum <= 10^9 1<=n<=maxSum<=109
0 < = i n d e x < n 0 <= index < n 0<=index<n
题目分析:
用例2构成的数组可能为 nums = [2,3,2,1,1,1] , 数组的和 sum = 8 < 10 满足要求。当nums[index] = 4时,
nums = [3,4,3,2,1,1] , 数组的和 sum = 14 > 10 不满足要求。所以最终返回的nums[index] 的最大值为 3。
我就可以使用二分的方式来寻求nums[index] 的最大值。此时二分的值为 mid , 指定此时nums[index] 的值为mid,如果此时数组的和 sum <= maxSum , l = mid(因为我们要求的是nums[index] 的最大值);如果 sum > maxSum 说明mid选择的值太大了,需要缩小,故 r = mid - 1。
边界问题:
右边也是类似的情况
- 时间复杂度: O ( l o g n ) O(logn) O(logn)
C++代码
class Solution {
public:
long long get(int b,int n){
return (b - n + 1 + b) * 1LL * n / 2;
}
int maxValue(int n, int index, int maxSum) {
int l = 1,r = maxSum;
while(l<r){
int mid = (l + r + 1) >> 1;
long long sum = 0LL;
if(index + 1 >= mid){
sum += get(mid,mid);
sum += index + 1 - mid;
}
else{
int len = index + 1;
sum += get(mid,len);
}
if(n - index >= mid){
sum += get(mid,mid);
sum += n - index - mid;
}
else{
int len = n - index;
sum += get(mid,len);
}
sum -= mid;
if(sum <= maxSum) l = mid;
else r = mid - 1;
}
return l;
}
};
Java代码
class Solution {
//返回 最后一项是 m 数量是cnt 的等差数列的和(第一项就是 m - cnt + 1)
//用 long 是为了避免溢出
private long get(int m,int cnt){
return (m - cnt + 1 + m) * 1L * cnt / 2;
}
public int maxValue(int n, int index, int maxSum) {
int l = 1,r = maxSum;
while(l<r){
int mid = (l + r + 1) >> 1;
long sum = 0L;
//此时的cnt 是包括 mid 在内的左边的元素个数
int cnt = index + 1;
if(cnt >= mid){
sum += get(mid,mid);
sum += cnt - mid;
}
else sum += get(mid,cnt);
//此时的cnt 是包括mid在内的右边的元素个数
cnt = n - index;
if(cnt >= mid){
sum += get(mid,mid);
sum += cnt - mid;
}
else sum += get(mid,cnt);
//因为加了2个mid 所以需要减去1个
sum -= mid;
//如果此时的sum <= maxSum 说明此时的mid是符合条件的 用mid来更新 l
if(sum <= maxSum) l = mid;
//不满足的话 包括mid在内的右边的数都会不满足,所以让 r 更新为 mid - 1
else r = mid - 1;
}
return l;
}
}