zoukankan      html  css  js  c++  java
  • 42 最大子数组Ⅱ

    原题网址:https://www.lintcode.com/zh-cn/old/problem/maximum-subarray-ii/#

    42. 最大子数组 II 

     

    讨论区 

    给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大。
    每个子数组的数字在数组中的位置应该是连续的。
    返回最大的和。

     注意事项

    子数组最少包含一个数

    样例

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

    挑战 

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

    标签 
     
     
    思路:
    对这种求两个数组不重叠区间的问题我是真的非常容易大脑死机,一上来就是确定两个区间的边界,不重叠时 end1 < begin2  --------一把心塞泪,这样走下去当然是想不出解法的。
    然后想到一种比较笨的解法,就是遍历nums,每次遍历数组分为左侧部分(0~i)和右侧部分(i+1~n-1),再分别求左侧部分最大子数组和与右侧部分最大子数组和(又是两个for循环),如果左右两个最大子数组和大于初始设定的sum(int型的最小值),就更新sum。这样在编译器运行正常,但是提交代码到lintcode上就超出时间限制了。时间复杂度是O(n*n)。
     
    想了下这个方法的主要问题是重复计算,在网上看了别人的答案后恍然大悟,可以用数组将每次的运算结果保存起来,即:
    定义两个数组left与right,与nums等长,分别记录每个位置左侧最大子数组和与右侧最大子数组和;
    从左往右遍历,计算i左侧部分的最大子数组和left【i】;
    再从右往左遍历,计算i右侧部分的最大子数组和right【i】;
    遍历left与right,left[k]+right[k+1]表示在第k位拆分数组,得到其子数组的和,找到最大值return出去就可以了。
     
    AC代码:
    class Solution {
    public:
        /*
         * @param nums: A list of integers
         * @return: An integer denotes the sum of max two non-overlapping subarrays
         */
        int maxTwoSubArrays(vector<int> &nums) {
            // write your code here
            if (nums.size()==0)
        {
            return 0;
        }
        int n=nums.size();
        vector<int> left(n,0);
        vector<int> right(n,0);
        int maxSum1=nums[0],sum1=0;
        int maxSum2=nums[n-1],sum2=0;
        int i=0,j=n-1;
        for (;i<n;i++)
        {
            sum1+=nums[i];
            if (sum1>maxSum1)
            {
                maxSum1=sum1;
            }
            if (sum1<0)
            {
                sum1=0;
            }
            left[i]=maxSum1;
        }
        
        for (;j>=0;j--)
        {
            sum2+=nums[j];
            if (sum2>maxSum2)
            {
                maxSum2=sum2;
            }
            if (sum2<0)
            {
                sum2=0;
            }
            right[j]=maxSum2;
        }
    
        int sum=left[0]+right[1];    
        for (int k=1;k<n-1;k++)//k=n-1时left为整个nums的最大子数组和,不符合子数组不重叠要求,且right下标超出范围;
        {
            if (left[k]+right[k+1]>sum)
            {
                sum=left[k]+right[k+1];
            }
        }
    
        return sum;
        }
    };

     还可以直接计算 0~k 与 k+1~n-1 部分的最大子数组和,修改代码如下:

    class Solution {
    public:
        /*
         * @param nums: A list of integers
         * @return: An integer denotes the sum of max two non-overlapping subarrays
         */
        int maxTwoSubArrays(vector<int> &nums) {
            // write your code 
            if (nums.size()==0)
        {
            return 0;
        }
        int n=nums.size();
        vector<int> left(n,0);
        vector<int> right(n,0);
        int maxSum1=nums[0],sum1=0;
        int maxSum2=nums[n-1],sum2=0;
        int i=0,j=n-1;
        for (;i<n;i++)//计算0~k的最大子数组和;
        {
            sum1+=nums[i];
            if (sum1>maxSum1)
            {
                maxSum1=sum1;
            }
            if (sum1<0)
            {
                sum1=0;
            }
            left[i]=maxSum1;
        }
        
        for (;j>0;j--)//计算k+1~n-1的最大子数组和;
        {
            sum2+=nums[j];
            if (sum2>maxSum2)
            {
                maxSum2=sum2;
            }
            if (sum2<0)
            {
                sum2=0;
            }
            right[j-1]=maxSum2;
        }
    
        int sum=left[0]+right[0];    
        for (int k=1;k<n-1;k++)//k=n-1时left为整个nums的最大子数组和,不符合子数组不重叠要求;
        {
            if (left[k]+right[k]>sum)
            {
                sum=left[k]+right[k];
            }
        }
    
        return sum;
        }
    };
     
     
     
     
  • 相关阅读:
    Oracle数据库的dual表的作用
    数据库中CASE函数和Oracle的DECODE函数的用法
    Oracle数据库中,通过function的方式建立自增字段
    Java学习(十三):抽象类和接口的区别,各自的优缺点
    Java学习(十八):二叉树的三种递归遍历
    Sublime工具插件安装
    sizeof和strlen
    I2C接口的EEPROM操作
    关于窗口看门狗
    关于指针传入函数
  • 原文地址:https://www.cnblogs.com/Tang-tangt/p/9080111.html
Copyright © 2011-2022 走看看