410. Split Array Largest Sum
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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: Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000. Examples: Input: nums = [7,2,5,10,8] m = 2 Output: 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.
二分法:
public int splitArray(int[] nums, int m) { long sum = 0; int max = 0; for(int num: nums){ max = Math.max(max, num); sum += num; } return (int)binarySearch(nums, m, sum, max); } //二分查找 private long binarySearch(int[] nums, int m, long high, long low){ long mid = 0; while(low < high){ mid = (high + low)/2; //验证是否满足,也就是这么大的值有可能出现么 if(valid(nums, m, mid)){ high = mid; }else{ low = mid + 1; } } return high; } /** * 验证这个值是否合法 * */ private boolean valid(int[] nums, int m, long max){ int cur = 0; int count = 1; //是否有多余m个片段or区间,大于给定值的max的,如果有了,那么就不合法了,因为这样划分就不止m个,及max太小 for(int num: nums){ cur += num; if(cur > max){ cur = num; count++; if(count > m){ return false; } } } return true; }
动归: 最大, 最小, 不能排序, 而且是求区间和的改写, 先考虑用一维动归, dp[m]表示分为m组, 写不出状态转移方程. 并且, 这是最大值最小的问题, 先找最大, 再找最小, 所以用二维数组, 题中就是组数, 和第几个人是变量, 因此dp[m][n] 表示将n个人分为m组的结果值, 这样有了两层外循环, 看递推公式与两层外循环的关系:
dp[m][n] = min (dp[m][n], Un-1 j = m - 1 max(dp[m - 1][j], sum[n] - sum[j]) (内循环多是最后一次分割点位置变化, 和前一次分割的关系 )
因为dp[m - 1][j] 不能直接得到, 所以需要 外循环 动归到dp[m][n], 其实想想也很简单, 只有外循环先建立起来了, 才有内循环的递推公式.
一维状态方程常考虑: 要不要该点,
二维状态方程常考虑: 分割点(与题目的值(sums[j] - sums[k]) 联系最紧密 , 当前分割的次数与前一次数有什么关系
subarray 和的问题常转化为 区间和的问题, (sums[j] - sums[k])
起点的初始化要正常, 中间点的初始化时为了比较(min, max) 等.------知道的初始化正常值, 不知道的初始化为对立值.
public int splitArray(int[] nums, int m) { int n = nums.length; int[][] dp = new int[m + 1][nums.length + 1]; int[] sums = new int[n + 1]; for (int i = 1; i <= n; ++i) { sums[i] = sums[i - 1] + nums[i - 1]; } for (int i = 0; i <= m; ++i) { for (int j = 0; j <= n; ++j) { dp[i][j] = Integer.MAX_VALUE; } } dp[0][0] = 0; for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { for (int k = i - 1; k < j; ++k) { int val = Math.max(dp[i - 1][k], sums[j] - sums[k]); dp[i][j] = Math.min(dp[i][j], val); } } } return dp[m][n]; }
以上是关于410. Split Array Largest Sum的主要内容,如果未能解决你的问题,请参考以下文章