410. 分割数组的最大值
给定一个非负整数数组 nums 和一个整数 m ,你需要将这个数组分成 m 个非空的连续子数组。
设计一个算法使得这 m 个子数组各自和的最大值最小。
:
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/split-array-largest-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
未优化的动态规划
class Solution {
private static int[] getPreSum(int[] nums) {
int n = nums.length;
int[] preSum = new int[n];
preSum[0] = nums[0];
for (int i = 1; i < nums.length; ++i) {
preSum[i] = preSum[i - 1] + nums[i];
}
return preSum;
}
private static int getRegionSum(int[] preSum, int l, int r) {
return l == 0 ? preSum[r] : preSum[r] - preSum[l - 1];
}
public static int splitArray(int[] nums, int m) {
if (nums == null || nums.length == 0) {
return 0;
}
// dp[i][j] [0, i] 分为 j份
int n = nums.length;
int[] preSum = getPreSum(nums);
int[][] dp = new int[n][m];
// [0, i] 分为 1份
for (int i = 0; i < n; ++i) {
dp[i][0] = getRegionSum(preSum, 0, i);
}
for (int i = 1; i < n; ++i) {
for (int j = 2; j <= Math.min(m, i + 1); ++j) {
dp[i][j - 1] = Integer.MAX_VALUE;
for (int k = j - 1; k <= i; ++k) {
dp[i][j - 1] = Math.min(dp[i][j - 1], Math.max(dp[k - 1][j - 2], getRegionSum(preSum, k, i)));
}
}
}
return dp[n - 1][m - 1];
}
}
优化的动态规划
class Solution {
private static int[] getPreSum(int[] nums) {
int n = nums.length;
int[] preSum = new int[n];
preSum[0] = nums[0];
for (int i = 1; i < nums.length; ++i) {
preSum[i] = preSum[i - 1] + nums[i];
}
return preSum;
}
private static int getRegionSum(int[] preSum, int l, int r) {
return l == 0 ? preSum[r] : preSum[r] - preSum[l - 1];
}
public static int splitArray(int[] nums, int m) {
if (nums == null || nums.length == 0) {
return 0;
}
// dp[i][j] [0, i] 分为 j份
int n = nums.length;
int[] preSum = getPreSum(nums);
int[][] dp = new int[n][m];
int[][] choose = new int[n][m];
// [0, i] 分为 1份
for (int i = 0; i < n; ++i) {
dp[i][0] = getRegionSum(preSum, 0, i);
}
for (int i = 1; i < n; ++i) {
for (int j = Math.min(m, i + 1); j >= 2; --j) {
dp[i][j - 1] = Integer.MAX_VALUE;
int down = Math.max(j - 1, choose[i - 1][j - 2]);
int up = Math.min(i, j == Math.min(m, i + 1) ? i : choose[i][j]);
for (int k = down; k <= up; ++k) {
int next = Math.max(dp[k - 1][j - 2], getRegionSum(preSum, k, i));
if (dp[i][j - 1] > next) {
dp[i][j - 1] = next;
choose[i][j - 1] = k;
}
}
}
}
return dp[n - 1][m - 1];
}
}
二分
import java.util.Arrays;
class Solution {
private static boolean trySplit(int[] nums, int m, int target) {
int count = 1;
int sum = 0;
for (int num : nums) {
sum += num;
if (sum > target) {
count++;
sum = num;
}
}
return count <= m;
}
public static int splitArray(int[] nums, int m) {
if (nums == null || nums.length == 0) {
return 0;
}
int left = Arrays.stream(nums).max().getAsInt();
int right = Arrays.stream(nums).sum();
int ret = right;
while (left <= right) {
int mid = (left + right) >> 1;
if (trySplit(nums, m, mid)) {
ret = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ret;
}
}
心之所向,素履以往 生如逆旅,一苇以航

浙公网安备 33010602011771号