Leetcode 410. Split Array Largest Sum

Posted haoweizh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode 410. Split Array Largest Sum相关的知识,希望对你有一定的参考价值。

Problem:

 

Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

 

Note:
If n is the length of array, assume the following constraints are satisfied:

 

  • 1 ≤ n ≤ 1000
  • 1 ≤ m ≤ min(50, n)

 

Examples:

 

Input:
nums = [7,2,5,10,8]
m = 2

Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.

 

Solution:

  看到极小化极大值的问题,我的第一个想法就是动态规划,一般来说,这类极小化极大值或极大化极小值问题大概率都是用动态规划来做,而且还有一个特性,就是动态规划一般会把一维问题上升到三维的时间复杂度,比如Leetcode 375。照这个思路往下走,如何进行规划呢。首先是维护一个二维数组,dp[i][j]表示在第j个数之前把子数组分为i份的最小的最大值(有点绕,意思是第j个数之前可能有多种分法,每种分法都有一个和最大的子数组,dp[i][j]即所有分法中最小的最大值),因此,如果将第j个数之前把它分为i+1份,则从i到j进行循环(因为第i个数之前不可能分为i份),计算dp[i][t]和sum[j]-sum[t]中的较大值,在这i到j之间寻找这个较大值的最小值赋给dp[i+1][j],代码如下

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

  然而这道题还没有结束,通过提交效率的直方图我发现有两个距离差的较远的高峰,而且标签还有一个诡异的Binary Search,这说明这道题还有一个二分搜索的解法。首先我们可以断定答案落在区间[max(nums),sum(nums)]之间,所以我们在这个区间内做二分搜索,并判断当结果为pivot时至少可以分为多少部分,找到最小可以满足分为m份的值。

Code:

 

 1 class Solution {
 2 public:
 3     int splitArray(vector<int>& nums, int m) {
 4         int left = 0;
 5         int right = 0;
 6         for(int i = 0;i != nums.size();++i){
 7             left = max(left,nums[i]);
 8             right += nums[i];
 9         }
10         while(left < right){
11             int pivot = left+(right-left)/2;
12             int count = 1;
13             int sum = 0;
14             for(int i = 0;i != nums.size();++i){
15                 sum += nums[i];
16                 if(sum > pivot){
17                     sum = nums[i];
18                     count++;
19                 }
20             }
21             if(count <= m)
22                 right = pivot;
23             else
24                 left = pivot+1;
25         }
26         return left;
27     }
28 };

 


以上是关于Leetcode 410. Split Array Largest Sum的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 410. Split Array Largest Sum

leetcode410 Split Array Largest Sum

410. Split Array Largest Sum

410. Split Array Largest Sum

410. Split Array Largest Sum

410. Split Array Largest Sum