• 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

    简书程序

    好像就这个方法了

  • 相关阅读:
    mysql主从只同步部分库或表
    springboot~aspect通过@annotation进行拦截
    ELK~fluentd将日志文件增量读到es里
    怎么自学 Java ?和盘托出
    一个后端开发的 Vue 笔记【入门级】
    企业级数据大屏设计如何实现
    Vue.js官方中文教程
    vue学习笔记 ---- 系列文章
    基于Asp.net core Kestrel的超迷你http服务器 ---- AServer
    Docker学习—概念及基本应用
  • 原文地址:https://www.cnblogs.com/theskulls/p/5106830.html
Copyright © 2020-2023  润新知