首页 > 学院 > 开发设计 > 正文

Leetcode 410 - Split Array Largest Sum(dp or 二分答案)

2019-11-14 12:43:42
字体:
来源:转载
供稿:网友

题意

给定一个数组,将数组划分m组,要求每组的和的最大值最小

思路

算法1:dp

首先我们这样考虑:我们要将前n个元素划分成m段,即先找一个划分点k,在[k + 1, n]不再划分。然后将[1, k]划分成m - 1段。那么就可以得到我们的状态表示和转移方程。

状态表示d[i,j],前i个元素,划分成j段的最大和。 转移方程d[i,j]=min{max0≤k<i{d[k,j−1]},∑p=k+1jap} 时间复杂度O(n2m)

算法2:二分

最大值最小问题一般采用二分答案的方法。

我们二分一下我们最后的答案,判断答案是否合法即可。 判断数x是否合法:统计一下将数组划分为最大值≤x时能划分多少组。如果组数cnt>x,则说明我们答案应该更大,否则,答案可以减小。

代码

//algorithm 1: dpconst int maxn = 1005;const int maxm = 55;int d[maxn][maxm];class Solution {public: int splitArray(vector<int>& nums, int m) { int n = nums.size(); if (n == 0) return 0; int S[maxn]; S[0] = nums[0]; for (int i = 1; i < n; i++) S[i] = S[i - 1] + nums[i]; for (int i = 0; i < n; i++) d[i][1] = S[i]; for (int j = 2; j <= m; j++) { for (int i = 0; i < n; i++) { d[i][j] = INT_MAX; for (int k = 0; k < i; k++) d[i][j] = min(d[i][j], max(d[k][j - 1], S[i] - S[k])); } } return d[n - 1][m]; }};//algorithm 2: Binary Searchclass Solution {public: bool judge(long long x, int m, vector<int> nums) { int cnt = 0; bool f = false; long long sum = 0; for (int i = 0; i < nums.size(); i++) { if ((long long)nums[i] > x) return false; sum += nums[i]; if (i == nums.size() - 1) { if (sum > x) cnt += 2; else cnt++; } else { if (sum > x) { cnt++; sum = nums[i]; } } } if (cnt > m) return false; return true; } int splitArray(vector<int>& nums, int m) { int n = nums.size(); if (n == 0) return 0; long long sum = nums[0], MIN = nums[0]; for (int i = 1; i < n; i++) {sum += nums[i]; MIN = min(MIN, (long long)nums[i]);} long long L = MIN, R = sum, M = L + (R - L) / 2, res = sum; while (L < R) { if (R == L + 1) { if (judge(L, m, nums)) M = L; else M = R; break; } M = L + (R - L) / 2; if (judge(M, m, nums)) R = M; else L = M; } return M; }};
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表