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

    简书程序

    好像就这个方法了

  • 相关阅读:
    一篇文章弄懂flex布局
    angularjs中使用锚点,angular路由导致锚点失效的两种解决方案
    CSS修改选中文本颜色与背景色
    记一个bootstrap定制container导致页面X轴出现横向滚动条的坑
    bootstrap去除自带15px内边距,去除container 15px padding
    手摸手教你bootstrap定制
    js中call、apply、bind到底有什么区别?bind返回的方法还能修改this指向吗?
    js 为何范围内随机取整要用floor,而不是ceil或者round呢
    js random获取随机数,获取任意范围内随机整数
    详解 Web基本概念
  • 原文地址:https://www.cnblogs.com/theskulls/p/5106830.html
Copyright © 2011-2022 走看看