410. Split Array Largest Sum
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.
Approach #1: Plan Recursion (Up to Bottom)
class Solution { public: int splitArray(vector<int>& nums, int m) { const int n = nums.size(); sums_ = vector<int>(n); mem_ = vector<vector<int>>(n, vector<int>(m + 1, INT_MAX)); sums_[0] = nums[0]; for (int i = 1; i < n; ++i) { sums_[i] = nums[i] + sums_[i-1]; // prefix sum } return helper(nums, n-1, m); } private: int helper(const vector<int>& nums, int k, int m) { if (m == 1) return sums_[k]; // split one group. if (m > k + 1) return INT_MAX; // split groups more than the elements. if (mem_[k][m] != INT_MAX) return mem_[k][m]; // return the have memeried status int ans = INT_MAX; for (int i = 0; i < k; ++i) ans = min(ans, max(helper(nums, i, m-1), sums_[k] - sums_[i])); // calculation minimize largest sum. return mem_[k][m] = ans; } vector<vector<int>> mem_; vector<int> sums_; };
Runtime: 116 ms, faster than 2.38% of C++ online submissions for Split Array Largest Sum.
Approach #2: DP (Bottom to Up)
class Solution { public: int splitArray(vector<int>& nums, int m) { const int n = nums.size(); // if I don't use const it will not compile successfully. vector<int> sum(n+1); vector<vector<int>> dp(m+1, vector<int>(n, INT_MAX)); sum[0] = nums[0]; for (int i = 1; i < n; ++i) sum[i] = sum[i-1] + nums[i]; for (int i = 0; i < n; ++i) dp[1][i] = sum[i]; // the status with only one group; for (int i = 2; i <= m; ++i) { for (int j = i-1; j < n; ++j) { for (int k = 0; k < j; ++k) { dp[i][j] = min(dp[i][j], max(dp[i-1][k], sum[j] - sum[k])); } } } return dp[m][n-1]; } };
Runtime: 116 ms, faster than 2.38% of C++ online submissions for Split Array Largest Sum.
Approach #3: Binary Search:
class Solution { public: int splitArray(vector<int>& nums, int m) { int l = 0, r = 0; for (auto& num : nums) { // if don't use auto& it won't compile successfully. l = max(l, num); r += num; // the answer must exsit bewteen in the l and r. } while (l <= r) { int mid = l + (r - l) / 2; if (canSplit(nums, m, mid)) r = mid - 1; else l = mid + 1; } return l; } private: bool canSplit(vector<int>& nums, int m, int mid) { int c = 1; int sum = 0; for (auto& num : nums) { sum += num; if (sum > mid) { c++; sum = num; } } return c <= m; } };
Runtime: 4 ms, faster than 49.91% of C++ online submissions for Split Array Largest Sum.
永远渴望,大智若愚(stay hungry, stay foolish)