持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
描述
给你一个下标从 0 开始的数组 nums ,它含有 n 个非负整数。
每一步操作中,你需要:
- 选择一个满足
1 <= i < n的整数i,且nums[i] > 0。 - 将
nums[i]减 1 。 - 将
nums[i - 1]加 1 。
你可以对数组执行 任意 次上述操作,请你返回可以得到的 nums 数组中 最大值 最小 为多少。
n == nums.length2 <= n <= 10^50 <= nums[i] <= 10^9
思路
题意要求我们找出一个在符合操作下的最大值最小化
一般这类问题如何思考呢?
我们可以直接从最大值最小化这一点开始入手
根据题意,我们可以对 nums[i] 操作,但会让nums[i-1]变化
欸,有传递性!
我们对nums[i] - 1操作之后,我们的nums[i-1]就会 + 1
那么,我们再次对nums[i-1]进行操作,我们的nums[i-2]就会+1
...
持续下去,最后,我们可以发现,我们的值都会被累加到第一个数字去
这本不是我们想看见的,我们想的是尽可能的平均大家的值,可以平分到的最小的最大值
那么,一个比这个值大的最大值是不是一定可能呢?
显然是的,证明如下:
于是,我们可以二分答案,去二分出最小的可以枚举出来的值是多少!
代码
class Solution {
public:
int minimizeArrayValue(vector<int>& nums) {
#define int long long
int sum = 0, r = 0;
for_each(begin(nums), end(nums), [&](int v) {sum += v; r = max(r, v);});
int l = sum / nums.size();
vector<int> tm(nums.size());
while (l < r) {
int x = l + r >> 1;
for (int i = 0; i < nums.size(); i ++) tm[i] = nums[i];
for (int i = tm.size() - 1; i; i --)
if (tm[i] > x) tm[i-1] += tm[i] - x;
if (tm[0] > x) l = x + 1;
else r = x;
}
return r;
#undef int
}
};