Problem 3 Split Array Largest Sum
Step 1 dp definition
dp[k][i] represent the smallest largest sum we can get using first i element to parition into k pieces
用i个元素,分成k份,minimized largest sum是多少
Step 2 base case
dp[1][i] = sum of array[j], j = 1, ...., i
dp[any][0] = XXX 没得可分,invalid case
dp[1][any] = 不用分,不用分就是所有元素= sum of elements!!
Step3: Induction Rule
dp[k][i] = min of maximum in (dp[k - 1][j] (左大段) , sum[array[j+1], ... array[i]])
= minimum of all the way to parition, in each partition: maximum in (dp[k - 1])[j], prefixSum[n] -prefixSum[j])
左大段,右小段
length = j 左大段 | 右小段 index range: j to n-1
注意
注意那部分sum可以用prefix Sum
[0, arr[0], arr[0] + arr[1],....., arr[0] + arr[1] ... arr[j],..., arr[0] + ...+ arr[n - 1]]
0, 1, 2.....j,...,n
use case: sum of range [j, n - 1]
[0, ... j - 1], [0, ... n- 1] ===>. (j - 1, n-1]
sum of range [0, j - 1]: prefixSum[j]
sum of range[0, n - 1]: prefixSum[n]
sum or range[j, n - 1]: prefixSum[n] - prefixSum[j]
左大段的长度j也不是随意:
不能切寂寞: j < 原始问题的长度 ==》 j <= n - 1
为了让子问题还能分成k-1份,左大的段长度至少需要有长度k- 1
valid range: [k - 1, 愿问题的长度 - 1]
public int splitArray(int[] nums, int m) {
int[] prefix = new int[nums.length + 1];
for (int i = 0; i < prefix.lengthl i++) {
prefix[i+ 1] = prefix[i] + nums[i];
}
/*
唯一的区别:在于i的物理意义:一个是array里的index,一个是off by 1以后的index
for (int i = 0; i < nums.length; i++) {
prefixSum[i] = prefixSum[i - 1] + nums[i];
}
*/
int[][] dp = new int[n+ 1][nums.length + 1];
for (int[] temp: dp){
Arrays.fill(temp, Integer.MAX_VALUE);
}
// base case: dp[1][any]
for (int i = 0; i <= nums.length; i++) {
dp[1][i] = prefix[i];
}
for (int k = 2; k < m; k++) {
for (int n = k; n <= nums.length; n++) {
if (n == k) {
dp[k][n] = Math.max(dp[k - 1][n - 1], nums[n - 1]);
} else {
for (int j = k - 1; j < = n- 1; j++) {
dp[k][n] = Math.min(dp[k][n], Math.max(dp[k - 1][j], prefix[n] - prefix[j]))
}
}
}
}
return dp[m][nums.length];
}
TC & SC
O(n*n * k), O(n * k)
public int splitArray(int[] nums, int m) {
int[] prefix = new int[nums.length + 1];
for (int i = 0; i < prefix.lengthl i++) {
prefix[i+ 1] = prefix[i] + nums[i];
}
if (m == 1){
return prefix[nums.length];
}
int[] dp = new int[nums.length + 1];
/
/ base case: dp[1][any]
for (int i = 0; i <= nums.length; i++) {
dp[i] = prefix[i];
}
for (int k = 2; k < m; k++) {
for (int n = k; n <= nums.length; n++) {
if (n == k) {
dp[n] = Math.max(dp[n - 1], nums[n - 1]);
} else {
for (int j = k - 1; j < = n- 1; j++) {
dp[n] = Math.min(dp[n], Math.max(dp[j], prefix[n] - prefix[j]))
}
}
}
}
return dp[nums.length];
}
Last updated