2.14 求数组的子数组之和的最大值

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;  
    }
	
}
posted @ 2020-11-24 13:51  BOTAK  阅读(82)  评论(0编辑  收藏  举报