方法一:二分查找
思路与算法
查找最大值用二分查找,范围的最小值为1,最大值为 maxSum。查找条件为区间和不超过 maxSum,相邻元素按照减 1 递减,直到为 1。
查找左右两个区间和,使用 cal 方法,big - 1为等差数列的最后一个,按照 length 得到等差数列的第一个,或者存在多余的 1。
分两种情况求和,(s1 + sn) * n / 2 + 额外存在的 1。
代码
class Solution {
public int maxValue(int n, int index, int maxSum) {
int left = 1, right = maxSum;
// 二分查找最大值
while (left < right) {
int mid = (left + right + 1) / 2;
if (valid(mid, n, index, maxSum)) {
left = mid;
} else {
right = mid - 1;
}
}
return left;
}
// 总和是否小于等于 maxSum
public boolean valid(int mid, int n, int index, int maxSum) {
int left = index;
int right = n - index - 1;
return mid + cal(mid, left) + cal(mid, right) <= maxSum;
}
// 左右区间求和
public long cal(int big, int length) {
if (length + 1 < big) {
int small = big - length;
// 等差数列求和
return (long) (big - 1 + small) * length / 2;
} else {
int ones = length - (big - 1);
// 等差数列求和加上多余的1
return (long) big * (big - 1) / 2 + ones;
}
}
}
复杂度分析
时间复杂度:O(log(maxSum)),二分查找时间复杂度
空间复杂度:O(1),常数空间