解法一:模拟
此题的模拟分为两个阶段。首先把地面铺满,这样一定是满足要求的,然后在index处开始累加即可。在第一阶段咱们直接模拟,index处的值每次加一,这个值减去2就是他每次辐射到的范围。当两边都被辐射到,即进入第二阶段后,可以直接用简单除法完成。
class Solution {
public:
int maxValue(int n, int index, int maxSum) {
int sum = n;
int ret = 1;
while(1)
{
ret += 1;
sum += 1;
sum += min(index, ret-2);
sum += min(n-index-1, ret-2);
if(sum > maxSum)return ret-1;
// 提前终止
if(index < ret-2 && n-index-1 < ret-2)
{
return (maxSum-sum)/n + ret;
}
}
}
};
解法二:二分
接下来考虑另一种思路,给定一个index位置的值,我们能否判断当前和?答案是肯定的。这个计算相对并不复杂。因此,我们就可以用二分来解决这个问题,不断缩短区间直到找到目标。
代码这里做了一个简化,即计算左边还是右边都是一个区间问题,考虑当前最大值和区间长度即可。
typedef long long ll;
class Solution {
public:
ll partSum(ll x, ll len)
{
if(len <= 0)return 0;
if(len <= x)
{
ll min_val = x-len+1;
return (min_val+x)*len/2;
}
return (1+x)*x/2 + len-x;
}
ll sum(int x, int n, int index)
{
return x + partSum(x-1, index) + partSum(x-1, n-index-1);
}
int maxValue(int n, int index, int maxSum) {
// 进行二分查找
int l=1, r=maxSum;
while(l<r)
{
int mid = l + ceil((r-l)/2.0);
if(sum(mid, n, index) > maxSum)r = mid-1;
else l = mid;
}
return l;
}
};