2.14 求陣列的子陣列之和的最大值
阿新 • • 發佈:2020-11-24
2.14 求陣列的子陣列之和的最大值
基本問題:一個有N個正整數元素的一維陣列,這個陣列有很多子陣列,那麼子陣列之和的最大值是什呢嗎?
解法:
解法 : 動態規劃
動態規劃
狀態定義 : dp[i] 表示包含第i個元素的最大子序和
狀態轉移方程:dp[i] = max{dp[i-1] + arr[i] , arr[i]}
初始狀態:dp[0] = nums[0];
拓展問題:
- 1 如果陣列[A[0], ...,A[n-1]]首尾相連,題目又該如何解釋?
- 2 如果題目要求同時返回最大子陣列的位置,演算法應該如何改變?還能保持\(O(n)\)的時間複雜度麼?
all coding
// 2.14 求陣列的子陣列之和的最大值 class Test{ public static void main(String[] args) { /** 基本問題:一個有N個正整數元素的一維陣列,這個陣列有很多子陣列,那麼子陣列之和的最大值是什呢嗎? 解法: 解法 : 動態規劃 */ int[] arr = new int[]{1,-2,3,5,-3,2}; print(arr); System.out.println(maxSubArray2(arr)); print(maxSubArrayPos(arr)); } public static void print(int[] arr){ for(int i:arr) System.out.print(i+" "); System.out.println(); } /** 動態規劃 狀態定義 dp[i] 表示包含第i個元素的最大子序和 狀態轉移方程 dp[i] = max{dp[i-1] + arr[i] , arr[i]} 初始狀態: dp[0] = nums[0]; */ public static int maxSubArray(int[] nums) { if(nums==null || nums.length==0) return 0; int[] dp = new int[nums.length]; dp[0] = nums[0]; for(int i = 1;i <nums.length;i++){ dp[i] = Math.max(dp[i-1]+nums[i],nums[i]); } int res = Integer.MIN_VALUE; for(int num:dp) res = Math.max(num,res); return res; } /** 拓展問題: 1 如果陣列[A[0], ...,A[n-1]]首尾相連,題目又該如何解釋? 2 如果題目要求同時返回最大子陣列的位置,演算法應該如何改變?還能保持$O(n)$的時間複雜度麼? */ /** 拓展問題1: */ public static int maxSubArray2(int[] nums) { if(nums==null || nums.length==0) return 0; int[] dp = new int[nums.length*2]; dp[0] = nums[0]; for(int i = 1;i <nums.length*2;i++){ dp[i] = Math.max(dp[i-1]+nums[i%nums.length],nums[i%nums.length]); } int res = Integer.MIN_VALUE; for(int num:dp) res = Math.max(num,res); return res; } /** 拓展問題2: return [start,end] */ public static int[] maxSubArrayPos(int[] nums){ int[] dp = new int[nums.length]; dp[0] = nums[0]; for(int i = 1;i <nums.length;i++){ dp[i] = Math.max(dp[i-1]+nums[i],nums[i]); } int max = Integer.MIN_VALUE; for(int num:dp) max = Math.max(max,num); int[] res = new int[2]; for(int i = 0;i<dp.length;i++) if(dp[i] == max) res[1] = i; int start; for(start= res[1];max!=0;start--) max-=nums[start]; res[0] = start-1; return res; } }