410. Split Array Largest Sum
阿新 • • 發佈:2017-08-03
into false 變化 java public ons urn for follow
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