题目链接:点击这里
二分的精髓:函数单调性 + 计算内容重复
二分法的难点在于如何建模和check()条件, 其中可能会套用其他算法或者数据结构。
这里 a n s ans ans 与 m m m 是单调、负相关的,所以,考虑在 [ 0 , s u m ] [0,sum] [0,sum] 范围内二分找到一个 a n s ans ans 满足题目要求。
本题会爆掉int
AC代码:
class Solution {
public:
//问题变为:当最大值为mid时,求m最小是多少。
//贪心策略:能放则放。
bool check(long long mid, vector<int>& nums, int m)
{
long long sum = 0;
int cnt = 0;
for(int i = 0; i < nums.size(); i++)
{
if(sum + nums[i] > mid)
{
cnt++;
if(nums[i] > mid) return false;
sum = nums[i];
}
else
sum += nums[i];
}
return cnt < m;
}
int splitArray(vector<int>& nums, int m) {
long long sum = 0;
for(int i = 0; i < nums.size(); i++)
sum += nums[i];
long long L = 0, R = sum, mid, ans = 0; //[L,R]
while(L <= R)
{
mid = L+(R-L)/2;
if(check(mid, nums, m))
{
ans = mid;
R = mid - 1;
}
else
{
L = mid + 1;
}
}
return ans;
}
};
注意本题 a n s ans ans 与 m m m 是负相关的,check()函数与主函数的逻辑关系要理清。
AC代码:
class Solution {
public:
//问题变为:当最大值为mid时,求m最小是多少。
//贪心策略:能放则放。
bool check(long long mid, vector<int>& nums, int m)
{
long long sum = 0;
int cnt = 0;
for(int i = 0; i < nums.size(); i++)
{
if(sum + nums[i] >= mid)
{
cnt++;
if(nums[i] >= mid) return true;
sum = nums[i];
}
else
sum += nums[i];
}
return cnt >= m;
}
int splitArray(vector<int>& nums, int m) {
long long sum = 0;
for(int i = 0; i < nums.size(); i++)
sum += nums[i];
long long L = 0, R = sum, mid, ans = 0; //[L,R]
while(L <= R)
{
mid = L+(R-L)/2;
if(check(mid, nums, m))
{
ans = mid;
L = mid + 1;
}
else
{
R = mid - 1;
}
}
return ans;
}
};