题意分析
- 给你一个长度为n的序列,需要我们将这个序列分为连续的k部分,要求分的所有的情况里面,对于每个部分的数字的和,要求所有的部分数字的和的最小的最大化。
- 样例解释
有3种分法
[1],[2,1,5],数字和分别为1,8,最小值为1
[1,2][1,5],数字和分别为3,6,最小值为3
[1,2,1],[5]数字和分别为4,5,最小值为4
则最小值的最大值为4。
思路分析
- 我们知道,对于这种类型的题目,要我们求最小值最大化或者最大值最小化的情况,我们一般是可以使用二分的方法进行求解的。我们先利用二分枚举最后的结果。然后对于我们枚举的每个值,我们通过一个函数进行判断。那么这个函数如何判断呢?
- 我们发现,对于最后的结果,我们按照顺序进行划分,如果当前的值超过了我们枚举的mid,那么我们就可以将这些数字划分为同一部分,然后,我们判断最后的划分情况大于等于mid的有多少个,与k进行比较。如果比k大,那么说明我们的枚举的最小值还可以更大。否则,就更小。更新左右区间即可。
- judge函数如下
// 我们假设最小值为mid
bool judge(int k,int mid,vector<int>&a){
int num=0;
int sum=0;
for(auto x:a){
sum+=x;
if(sum>=mid){
num++;
sum=0;
}
}
return num>=k;
}写法一 C++版
- 代码如下
- 假设a数组的和为s,二分的时间复杂度为
,judge函数的判断的时间复杂度为
.所以总的时间复杂度为
- 只开了少数几个变量进行求解,空间复杂度为
- 假设a数组的和为s,二分的时间复杂度为
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @param k int整型
* @param a int整型vector
* @return int整型
*/
// 我们假设最小值为mid,那么小于最小值的就必须要添一个知道满足大于等于这个mid
bool judge(int k,int mid,vector<int>&a){
int num=0;
int sum=0;
for(auto x:a){
sum+=x;
// 如果这一部分的所有的数字的和大于等于mid,那么就把这些划分为一块
if(sum>=mid){
num++;
sum=0;
}
}
// 最后的块数和k进行比较
return num>=k;
}
int solve(int n, int k, vector<int>& a) {
// write code here
int l=0,r=0,mid;
for(auto x:a){
r+=x;
}
int ans=0;
while(l<=r){
mid=(l+r)>>1;
// std::cout<<"mid:"<<mid<<endl;
// 如果最后的结果大于等于mid,左边界右移
if(judge(k,mid,a)){
l=mid+1;
ans=max(ans,mid);
}else{
// 如果最后的结果小于mid,右边界左移
r=mid-1;
}
}
return ans;
}
};写法二 Go语言版
看写Go的不多,那么我来贡献一波go的代码。时间和空间都是100%,QAQ。
代码如下
- 假设a数组的和为
,二分的时间复杂度为
,judge函数的判断的时间复杂度为
.所以总的时间复杂度为
- 只开了少数几个变量进行求解,空间复杂度为
- 假设a数组的和为
package main
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @param k int整型
* @param a int整型一维数组
* @return int整型
*/
func solve( n int , k int , a []int ) int {
// write code here
l := 0
r := 0
// 先进行遍历得到所有的数字的和作为右边界
for _, value := range a {
r+=value
}
var mid int
ans := 0
for l<=r {
// 二分区间中点
mid = (l+r)/2
num := 0
sum := 0
for _, value := range a {
sum+=value
if(sum>=mid){
num++
sum=0
}
}
// 如果可以分的块数超过k,那么左边界右边移动
if(num>=k){
// 维护答案的最大值
if(ans<mid) {
ans=mid
}
l=mid+1
}else{
// 否则右边界左边移动
r=mid-1
}
}
return ans
}
京公网安备 11010502036488号