zoukankan      html  css  js  c++  java
  • lintcode:最大子数组差

    题目

    最大子数组差

    给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。

    返回这个最大的差值。

    样例

    给出数组[1, 2, -3, 1],返回 6

    注意

    子数组最少包含一个数

    挑战

    时间复杂度为O(n),空间复杂度为O(n)

    解题

     刚做了数组中两个子数组和的最大值,这一题是求差,感觉上题的求解思想应该是可以用的

    A B 分别是两个子数组的和,则:

    所以

    当A>B 的时候A越大越好 B越小越好

    当A<B 的时候B越大越好 A越小越好

    根据上一题的思想,定义leftMax数组,leftMax[i] 表示0到 i之间元素的全局最大值,定义rightMin矩阵,rightMin [i] 表示i 到 len -1 之间元素的全局最小值

    这样abs(leftMax[i] - rightMin[i+1]) 就是0到i 之间元素的最大值 减去 i + 1 到len-之间元素最小值 的绝对值,这个值得最大值就是两个子区间的 差的绝对值的最大值

    注意,这样还是有问题的,只是上面提交只能通过53%

    上面只是考虑的 A>B的情况,还需要考虑A<B的情况

    A >B 的情况是:leftMax - rightMin

    A<B  的情况是:rightMax - leftMin,具体思路参考上面的

    这样求出两个最大值的最大值就是答案了

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: An integer indicate the value of maximum difference between two
         *          Subarrays
         */
        public int maxDiffSubArrays(int[] nums) {
            // write your code here
            if(nums == null || nums.length ==0)
                return 0;
            int len = nums.length;
            int[] leftMax = new int[len];
            int[] rightMin = new int[len];
            int localMax = 0;
            int globalMax = Integer.MIN_VALUE;
            for(int i=0;i <len ;i++){
                localMax = Math.max(localMax + nums[i],nums[i]);
                globalMax = Math.max(localMax,globalMax);
                leftMax[i] = globalMax;
            }
            int localMin = 0;
            int globalMin = Integer.MAX_VALUE;
            for(int i=len-1;i >=0 ;i--){
                localMin = Math.min(localMin + nums[i],nums[i]);
                globalMin = Math.min(localMin,globalMin);
                rightMin[i] = globalMin;
            }
            int leftMAX = Integer.MIN_VALUE;
            for(int i=0;i<len-1;i++){
                leftMAX = Math.max(Math.abs(leftMax[i] - rightMin[i+1]),leftMAX);
            }
            
            int[] leftMin = new int[len];
            int[] rightMax = new int[len];
            localMin = 0;
            globalMin = Integer.MAX_VALUE;
            for(int i=0;i <len ;i++){
                localMin = Math.min(localMin + nums[i],nums[i]);
                globalMin = Math.min(localMin,globalMin);
                leftMin[i] = globalMin;
            }
            localMax = 0;
            globalMax = Integer.MIN_VALUE;
            for(int i=len-1;i >=0 ;i--){
                localMax = Math.max(localMax + nums[i],nums[i]);
                globalMax = Math.max(localMax,globalMax);
                rightMax[i] = globalMax;
            }
            int rightMAX = Integer.MIN_VALUE;
            for(int i=0;i<len-1;i++){
                rightMAX = Math.max(Math.abs(leftMin[i] - rightMax[i+1]),rightMAX);
            }
            
            return Math.max(leftMAX,rightMAX);
        }
    }
    Java Code

    显然上面程序太冗余了

    这里的方法和我想的一样

    这里也是的,只是部分循环在一起写了

    优化下

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: An integer indicate the value of maximum difference between two
         *          Subarrays
         */
        public int maxDiffSubArrays(int[] nums) {
            // write your code here
            if(nums == null || nums.length ==0)
                return 0;
            int len = nums.length;
            int[] leftMax = new int[len];
            int[] rightMin = new int[len];
            int[] leftMin = new int[len];
            int[] rightMax = new int[len];
            int localMax = 0;
            int globalMax = Integer.MIN_VALUE;
            int localMin = 0;
            int globalMin = Integer.MAX_VALUE;
            
            for(int i=0;i <len ;i++){
                localMax = Math.max(localMax + nums[i],nums[i]);
                globalMax = Math.max(localMax,globalMax);
                leftMax[i] = globalMax;
                
                localMin = Math.min(localMin + nums[i],nums[i]);
                globalMin = Math.min(localMin,globalMin);
                leftMin[i] = globalMin;
            }
            
            localMin = 0;
            globalMin = Integer.MAX_VALUE;
            localMax = 0;
            globalMax = Integer.MIN_VALUE;
            for(int i=len-1;i >=0 ;i--){
                localMin = Math.min(localMin + nums[i],nums[i]);
                globalMin = Math.min(localMin,globalMin);
                rightMin[i] = globalMin;
                
                localMax = Math.max(localMax + nums[i],nums[i]);
                globalMax = Math.max(localMax,globalMax);
                rightMax[i] = globalMax;
            }
            int leftMAX = Integer.MIN_VALUE;
            int rightMAX = Integer.MIN_VALUE;
            
            for(int i=0;i<len-1;i++){
                leftMAX = Math.max(Math.abs(leftMax[i] - rightMin[i+1]),leftMAX);
                rightMAX = Math.max(Math.abs(leftMin[i] - rightMax[i+1]),rightMAX);
            }
            
            return Math.max(leftMAX,rightMAX);
        }
    }
    Java Code

    简书程序

    好像就这个方法了

  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/theskulls/p/5106830.html
Copyright © 2011-2022 走看看