leetcode 410. 分割数组的最大值

深藏阁楼爱情的钟 2023-07-03 10:56 88阅读 0赞

思路1:动态规划.这题有点特殊。之前做过一道划分m段的和的最大值。难道其实比这题要高。

dp[i][j]表示前i个数分成j段得到的最大值的最小值(第i个一定包含在第j段里面)。所以我们要做的就是去枚举第j段的开始即可。为了方便求出任一段的和,先预处理求一个前缀和。

dp[i][j]=min(dp[i][j],max(dp[k][j-1],sum[i]-sum[k])

  1. class Solution {
  2. public:
  3. int splitArray(vector<int>& nums, int m) {
  4. int n=nums.size();
  5. unsigned long long dp[n+2][m+2];
  6. memset(dp,127,sizeof(dp));
  7. unsigned long long sum[n+3];
  8. sum[0]=0;
  9. dp[0][0]=0;
  10. for(int i=1;i<=n;i++)
  11. {
  12. sum[i]=sum[i-1]+nums[i-1];
  13. }
  14. for(int i=1;i<=n;i++)
  15. {
  16. for(int j=1;j<=m;j++)
  17. {
  18. for(int k=0;k<i;k++)
  19. {
  20. dp[i][j]=min(dp[i][j],max(dp[k][j-1],sum[i]-sum[k]));
  21. }
  22. }
  23. }
  24. return dp[n][m];
  25. }
  26. };

思路2:对于最大值最小化的问题,二分往往是正解。二分的思路是猜需要的最大值最小到底是谁,它的范围一定在[max(num[i],sum{num[i]}] 之间。所以在这个区间二分即可。

二分思路:每次取mid=(l+r)>>1 .然后遍历数组,看能划分的不超过mid的数组有多少个。记为cnt。若cnt>m 也就是以mid为最大值划分出来的数组,数量过多。那么说明mid过小。反之,mid过大。

  1. class Solution {
  2. public:
  3. int splitArray(vector<int>& nums, int m) {
  4. int n=nums.size();
  5. long long l=0,r=0;
  6. for(int i=0;i<n;i++)
  7. {
  8. r+=nums[i];
  9. l=max(l,(long long)nums[i]);
  10. }
  11. while(l<r)
  12. {
  13. long long mid=(l+r)>>1;
  14. int cnt=1;
  15. long long tmp=0;
  16. for(int i=0;i<n;i++)
  17. {
  18. tmp+=nums[i];
  19. if(tmp>mid)
  20. {
  21. tmp=nums[i];
  22. cnt++;
  23. }
  24. }
  25. if(cnt>m)
  26. {
  27. l=mid+1;
  28. }
  29. else
  30. {
  31. r=mid;
  32. }
  33. }
  34. return l;
  35. }
  36. };

发表评论

表情:
评论列表 (有 0 条评论,88人围观)

还没有评论,来说两句吧...

相关阅读