• lintcode:最大子数组II


    题目

    最大子数组 II

    给定一个整数数组,找出两个不重叠子数组使得它们的和最大。

    每个子数组的数字在数组中的位置应该是连续的。

    返回最大的和。

    样例

    给出数组[1, 3, -1, 2, -1, 2],这两个子数组分别为[1, 3][2, -1, 2]或者[1, 3, -1, 2][2],它们的最大和都是7

    注意

    子数组最少包含一个数

    挑战

    要求时间复杂度为O(n)

    解题

    最大子数组I 这个题目是求一个数组中一个最大子数组的和,而本题目是求数组中的前两个最大子数组的和。然后就想到定义两个数组:left 、right 。

    left[i] 表示从左开始到第i个值,并且包括第i个值的最大数组值

    right[i]表示从size-1开始到第i个值,并且包括第i个值的最大数组

    下面只需要找出两个数组和的最大值,并且两个数组的节点值不能有交集,这里需要遍历所有可能,时间复杂度是O(N2)

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: An integer denotes the sum of max two non-overlapping subarrays
         */
        public int maxTwoSubArrays(ArrayList<Integer> nums) {
            // write your code
            int size = nums.size();
            if(nums==null || size ==0)
                return 0;
            int[] left = new int[size];
            int[] right = new int[size];
            left[0] = nums.get(0);
            right[size-1] = nums.get(size-1);
            for(int i=1;i<size;i++){
                left[i] = Math.max(left[i-1] + nums.get(i),nums.get(i));
            }
            for(int j=size-2;j>=0 ;j--){
                right[j] = Math.max(right[j+1] + nums.get(j),nums.get(j));
            }
            int max = Integer.MIN_VALUE;
            for(int i=0;i<size;i++){
                for(int j=size-1;j>i ; j--){
                    int tmp = left[i] + right[j];
                    max = Math.max(max,tmp);
                }
            }
            return max;
        }
    }
    Java Code

    只求出左到右某个位置的最大子数组,再增加标志位来表示该位置是否是新的子数组的起始位置,然而后面不知道怎么搞了。

    参考博客 上面定义的left数组 还是right数组中的值 是包含当前元素的最大值是 局部最大值

    在上面博客中定义了全局最大值,这样定义的数组就是一个非降序的数组

    数组left ,left[i] 表示从0 到i 这个区间内元素的最大值

    同样可以求从i 到 size-1 这个区间的最大值

    上面两个值之和的最大值就是答案了

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: An integer denotes the sum of max two non-overlapping subarrays
         */
        public int maxTwoSubArrays(ArrayList<Integer> nums) {
            // write your code
            int size = nums.size();
            if(nums==null || size ==0)
                return 0;
            int max = Integer.MIN_VALUE;
            int left[] = new int[size];
            int localMax = 0;
            int globalMax = Integer.MIN_VALUE;
            for(int i=0;i< size;i++){
                localMax = Math.max(localMax+nums.get(i) , nums.get(i));
                globalMax = Math.max(localMax,globalMax);
                left[i] = globalMax;
            }
            localMax = 0;
            globalMax = Integer.MIN_VALUE;
            for(int i = size -1;i>=0;i--){
                if(i< size -1)
                    max = Math.max(max,globalMax+left[i]);
                localMax = Math.max(localMax + nums.get(i),nums.get(i));
                globalMax = Math.max(localMax,globalMax);
                
            }
            return max;
        }
    }
    Java Code

    上面的第二个for循环也就是求i 到size -1 区间内的全局最大值,然后就想到可以再定义一个数组

    right right[i] 表示从i 到 size -1这个区间的最大

    下面只需要根据这个两个数组求出最大值的和就好了

    max = Math.max(left[i] + right[i+1],max)

    再说明下:

    left[i] 表示从0 到i 这个区间的最大值

    right[i+1] 表示从 i + 1 都 size-1 这个区间的最大值

    显然上面的和的最大值就是答案了

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: An integer denotes the sum of max two non-overlapping subarrays
         */
        public int maxTwoSubArrays(ArrayList<Integer> nums) {
            // write your code
            int size = nums.size();
            if(nums==null || size ==0)
                return 0;
            int max = Integer.MIN_VALUE;
            int left[] = new int[size];
            int localMax = 0;
            int globalMax = Integer.MIN_VALUE;
            for(int i=0;i< size;i++){
                localMax = Math.max(localMax+nums.get(i) , nums.get(i));
                globalMax = Math.max(localMax,globalMax);
                left[i] = globalMax;
            }
            localMax = 0;
            globalMax = Integer.MIN_VALUE;
            int right[] = new int[size];
            for(int i = size -1;i>=0;i--){
                localMax = Math.max(localMax + nums.get(i),nums.get(i));
                globalMax = Math.max(localMax,globalMax);
                right[i] = globalMax;
            }
            for(int i=0;i< size-1;i++){
                max = Math.max(left[i] + right[i+1],max);
            }
            return max;
        }
    }
    Java Code

     Python

    class Solution:
        """
        @param nums: A list of integers
        @return: An integer denotes the sum of max two non-overlapping subarrays
        """
        def maxTwoSubArrays(self, nums):
            # write your code here    
            if not nums:
                return 0
    
            size = len(nums)
            left, right = [0 for i in range(size)], [0 for i in range(size)]
            MAX, localMax, globalMax = -sys.maxint - 1, 0, -sys.maxint-1
            for i in range(size):
                localMax = max(localMax+ nums[i],nums[i])
                globalMax = max(localMax,globalMax)
                left[i] = globalMax
            localMax = 0
            globalMax = -sys.maxint - 1
            for j in range(size-1,-1,-1):
                localMax = max(localMax + nums[j],nums[j])
                globalMax = max(localMax,globalMax)
                right[j] = globalMax
            for i in range(size-1):
                MAX = max(left[i] + right[i+1],MAX)
            return MAX
    Python Code

    这里为什么求了最小值,表示不理解

  • 相关阅读:
    根据屏幕大小,加载不同大小的图片
    规范命名CSS
    iframe框架加载完成后执行函数
    js获取IP地址
    80端口被System占用 造成Apache不能启动的解方案
    自定义一个仿Spinner
    让你的代码量减少3倍!使用kotlin开发Android(一)
    屏幕适配
    一个旋转菜单
    手势监听GestureDetector 案例
  • 原文地址:https://www.cnblogs.com/bbbblog/p/5106805.html
Copyright © 2020-2023  润新知