题意:
给定n个数字的序列,现在想把这个序列分成k段连续段,想知道分出来的k个连续段的段内数字和的最小值最大可以是多少?
方法一:
贪心
思路:计算a[]数组之和sum,则是该问题的理想情况的最大值。
因此可以贪心,以为最大值,值依次递减。
判断该值是否满足情况:如果满足,则return。
class Solution { public: int solve(int n, int k, vector<int>& a) { int sum=0;//sum是a数组之和 for(int i=0;i<n;i++){ sum+=a[i]; } for(int i=sum/k;i>=0;i--){//贪心,值从大到小遍历 if(f(a,k,i))//如果成功,return return i; } return 0; } int f(vector<int>& a,int k,int x){ int n=a.size();//a数组长度 int s=0;//初始和为0 for(int i=0;i<n;i++){ s+=a[i]; if(s>=x){ s=0; k--;//段数减一 if(k==0)//如果达到k段,则成功 return 1; } } return 0; } };
时间复杂度:空间复杂度:
方法二:
二分
思路:可以将方法一的贪心算法二分化。设L=0,R=。如果满足判断,则(扩大数值)否则(缩小数值)
class Solution { public: int solve(int n, int k, vector<int>& a) { int sum=0;//sum是a数组之和 for(int i=0;i<n;i++){ sum+=a[i]; } int l=0,r=sum/k,mid; while(l<r){ mid=(l+r+1)/2; if(f(a,k,mid))//如果满足,则l=mid l=mid; else//否则,r=mid-1 r=mid-1; } return l; } int f(vector<int>& a,int k,int x){ int n=a.size(); int s=0;//初始和为0 for(int i=0;i<n;i++){ s+=a[i]; if(s>=x){ s=0; k--;//段数减一 if(k==0)//如果达到k段,则成功 return 1; } } return 0; } };
时间复杂度:
空间复杂度: