本文涉及的基础知识点
下载及打开打包代码的方法兼述单元测试
C++二分查找
LeetCode2439. 最小化数组中的最大值
给你一个下标从 0 开始的数组 nums ,它含有 n 个非负整数。
每一步操作中,你需要:
选择一个满足 1 <= i < n 的整数 i ,且 nums[i] > 0 。
将 nums[i] 减 1 。
将 nums[i - 1] 加 1 。
你可以对数组执行 任意 次上述操作,请你返回可以得到的 nums 数组中 最大值 最小 为多少。
示例 1:
输入:nums = [3,7,1,6]
输出:5
解释:
一串最优操作是:
- 选择 i = 1 ,nums 变为 [4,6,1,6] 。
- 选择 i = 3 ,nums 变为 [4,6,2,5] 。
- 选择 i = 1 ,nums 变为 [5,5,2,5] 。
nums 中最大值为 5 。无法得到比 5 更小的最大值。
所以我们返回 5 。
示例 2:
输入:nums = [10,1]
输出:10
解释:
最优解是不改动 nums ,10 是最大值,所以返回 10 。
提示:
n == nums.length
2 <= n <= 105
0 <= nums[i] <= 109
二分查找
性质一:i < j 且nums[j]大于0,通过连锁反应,可以nums[j]–,nums[i]++。
二分类型:寻找首端
Check参数范围:[0,1e9]
Check函数:
long long can=0记录可以左移的数量 ,can += (mid-nums[i]),判断can是否小于0,小于0返回false。如果没有返回false,返回true。
用数学归纳证明正确性:任意前缀之和都小于等于mid*前缀长度。
长度为1的前缀如果符合,则nums[0]小于等于mid。
如果长度为n前缀的符合,且长度为n+1的前缀也符合。则num[n]将超出的部分前移。
代码
核心代码
template<class INDEX_TYPE>
class CBinarySearch
{
public:
CBinarySearch(INDEX_TYPE iMinIndex, INDEX_TYPE iMaxIndex):m_iMin(iMinIndex),m_iMax(iMaxIndex) {}
template<class _Pr>
INDEX_TYPE FindFrist( _Pr pr)
{
auto left = m_iMin - 1;
auto rightInclue = m_iMax;
while (rightInclue - left > 1)
{
const auto mid = left + (rightInclue - left) / 2;
if (pr(mid))
{
rightInclue = mid;
}
else
{
left = mid;
}
}
return rightInclue;
}
template<class _Pr>
INDEX_TYPE FindEnd( _Pr pr)
{
int leftInclude = m_iMin;
int right = m_iMax + 1;
while (right - leftInclude > 1)
{
const auto mid = leftInclude + (right - leftInclude) / 2;
if (pr(mid))
{
leftInclude = mid;
}
else
{
right = mid;
}
}
return leftInclude;
}
protected:
const INDEX_TYPE m_iMin, m_iMax;
};
class Solution {
public:
int minimizeArrayValue(vector<int>& nums) {
auto Check = [&](int mid) {
long long can = 0;
for (const auto& n : nums) {
can += mid - n;
if (can < 0) { return false; }
}
return true;
};
return CBinarySearch<int>(0, 1'000'000'000).FindFrist(Check);
}
};
单元测试
vector<int> nums;
TEST_METHOD(TestMethod1)
{
nums = { 0 };
auto res = Solution().minimizeArrayValue(nums);
AssertEx(0, res);
}
TEST_METHOD(TestMethod2)
{
nums = { 1'000'000'000 };
auto res = Solution().minimizeArrayValue(nums);
AssertEx(1'000'000'000, res);
}
TEST_METHOD(TestMethod11)
{
nums = { 3, 7, 1, 6 };
auto res = Solution().minimizeArrayValue(nums);
AssertEx(5, res);
}
TEST_METHOD(TestMethod12)
{
nums = { 10,1 };
auto res = Solution().minimizeArrayValue(nums);
AssertEx(10, res);
}