子数组之和最大值

问题描述

给定一个序列\(A_0\)、\(A_1\)、\(A_2\)、...、\(A_{n-1}\),求\(A_i+A_{i+1}+...+A_j\)的最大值。

解一

暴力枚举左端点\(i\)和右端点\(j\),之后计算\(A_i\)和\(A_j\)之间的和,时间复杂度\(O(n^3)\),很容易TLE。

#define INF 0x7FFFFFFF

int sub_sum(int a[],int n)
{
    int MAX = -INF;
    for(int i = 0;i < n;i++)
    {
        for (int j = i; j < n; j++)
         {
            int temp = 0;
            for (int k = i; k <= j; k++)
            {
                    temp += a[k];
            }
            if (temp > MAX)
            {
                MAX = temp;
            }
         }
    }
    return MAX;
}

解二

输入数据时记录前缀和,预处理\(sum[i] = A[0] + ... + A[i]\),因此\(A_i+A_{i+1}+...+A_j=sum[j]-sum[i-1]\),复杂度优化为\(O(n^2)\)。

int sub_sum(int a[],int n)
{
    int MAX = -INF;
    for(int i = 0;i < n;i++)
    {
        for(int j = i;j < n;j++}
        {
            int temp = sum[j] - sum[i - 1];
            if(temp > MAX)
                MAX = temp;
            else
                temp = 0;
        }
    }
    return MAX;
}

解三

动态规划,复杂度\(O(n)\)。
定义状态数组\(dp[i]\),表示以\(A[i]\)结尾的连续序列的最大和,这样就只有两种情况:
1,该连续序列只有\(A[i]\)这一个元素;
2,该序列有多个元素,从之前的\(A[p]\)开始,到\(A[i]\)结束。
对于1,最大和就是\(A[i]\);
对于2,最大和是\(dp[i - 1]+A[i]\),因为\(dp[i]\)要求以\(A[i]\)结尾,所以即使\(A[i]\)为负数,\(dp[i]\)仍然等于\(dp[i - 1]+A[i]\)。
所以状态转移方程就是:
\[dp[i]=max{\{A[i],dp[i-1]+A[i]\}}\]边界是\(dp[0]=A[0]\)。
所以枚举\(i\),得到\(dp\)数组,求出\(dp\)数组最大值即可。

可以看到,每次计算\(dp[i]\)只用到\(dp[i-1]\),不直接用到之前的信息,这就是状态的无后效性,只有这样,动态规划才可能得到正确结果。

int dp[5010];
dp[0] = a[0];

int sub_sum(int a[],int n)
{
    for(int i = 1;i < n;i++)
    {
        //状态转移方程
        dp[i] = max(a[i],dp[i - 1] + a[i]);
    }

    int k = 0;
    for(int i = 1;i < n;i++)
    {
        if(dp[i] > dp[k])
            k = i;
    }
    return dp[k];
}

为了避免使用\(dp[]\)数组,可以将空间复杂度优化为\(O(1)\):

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int allSum = INT_MIN, curSum = 0;

        int n = nums.size();
        for(int i = 0;i < n;i++)
        {
            curSum = max(nums[i], curSum + nums[i]);
            if(curSum > allSum)
            {
                allSum = curSum;
            }
        }

        return allSum;
    }
};

原文地址:https://www.cnblogs.com/EIMadrigal/p/12130801.html

时间: 2024-08-04 23:47:39

子数组之和最大值的相关文章

求子数组之和最大值

求子数组之和最大值 个人信息:就读于燕大本科软件工程专业 目前大三; 本人博客:google搜索"cqs_2012"即可; 个人爱好:酷爱数据结构和算法,希望将来从事算法工作为人民作出自己的贡献; 编程语言:C++ ; 编程坏境:Windows 7 专业版 x64; 编程工具:vs2008; 制图工具:office 2010 powerpoint; 硬件信息:7G-3 笔记本; 真言 让自己爆发吧,不要在安于现状了. 题目 求子数组之和最大值. 方案 我的算法执行如下,C++表示如下(

二维数组求子数组之和最大值(首尾相接, 圆柱)

问题:求二维数组的子数组之和的最大值(首尾相接,即形成圆柱) 成员: 陈晨:负责代码复审和代码测试计划 王颖瑞:负责程序分析,代码编程 思路:对于这个问题,我们可以结合之前的实验(二维数组求子数组之和的最大值和首尾相连一维数组的子数组之和的最大值),把为二维数组的列扩大二倍,之后想一维数组(首尾相连)一样,把二维数组分成不同的几个二维数组.之后就分开求不同的二维数组的子数组的最大值,最后之间比较,求出总的最大值. 代码: #include<iostream> using namespace s

二维数组子数组的最大值之和

题目:求一个二维数组中其子数组之和的最大值. 人员: 陈晨:负责程序编写. 王颖瑞:负责代码复审和代码测试. 思路:对于求二维数组的子数组之和,思路和求一维数组的相差不多,但需要分析更多的情况,我跟舍友讨论之后,之后写的.以下是我的思路: 1.确定子数组的最大上界,从第一行依次向下,规定最大子数组的范围. 2.对于规定好的最大子数组的范围,把最大子数组按照一列有几个数,分成几种不同的行.(如第一组只有一行,第二组有两行等,列数和数组的列数相同) 3.对于第二步产生的几个数组,进行一维数组求子数组

编程之美 2.14求数组的子数组之和的最大值

对于一个有N个元素的数组,a[0]~a[n-1],求子数组最大值. 如:数组A[] = [−2, 1, −3, 4, −1, 2, 1, −5, 4],则连续的子序列[4,−1,2,1]有最大的和6. 方法一:暴力 循环遍历,输出所有,判断最大的和 1 #include"iostream" 2 #define MAX 1001 3 using namespace std; 4 5 int main(){ 6 int n, a[MAX], sum , maxsum ; 7 8 cin &

编程之美之2.14 求数组的子数组之和的最大值

[题目] 一个有N个整数元素的一维数组(A[0],A[1],A[2],...A[n-1]),这个数组中当然有很多子数组,那么子数组之和的最大值是多少? 该子数组是连续的. 我们先来明确一下题意: (1)子数组意味着是连续的. (2)题目只需要求和,并不需要返回子数组的具体位置. (3)数组的元素是整数,所以数组可能包含正整数,负整数或者零. 举几个例子: 数组:[1,-2,3,5,-3,2]返回8 数组:[0,-2,3,5,-1,2]返回9 数组:[-9,-2,-3,-5,-3]返回8 [解法一

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].

求数组的子数组之和的最大值?

自己写的代码考虑未周全,引入了额外的空间复杂度: //求数组的子数组之和的最大值 #include <iostream> #define N 12 using namespace std; int main() { //int a[]={-5,2,3,-3,-2,3,1,-5}; //int a[]={-5,2,0,3,-2,3,4,5}; int a[]={1,-2,3,10,-4,7,2,-5}; int flag,max,i,j=0; int sum[N]={0}; //(1)记录子数组

第2章 数字之魅——子数组之和的最大值(二维)

子数组之和的最大值(二维) 问题描述 我们在前面分析了一维数组之和的最大值问题,那么如果是二维数组又该如何分析呢? 分析与解法 最直接的方法,当然就是枚举每一个矩形区域,然后再求这个矩形区域中元素的和. [解法一] 完整代码如下: 1 package chapter2shuzizhimei.maxsumsubarraytwodimensional; 2 /** 3 * 求数组的子数组之和的最大值(二维) 4 * [解法一] 5 * @author DELL 6 * 7 */ 8 public c

编程之美读书笔记2.14 - 子数组之和的最大值

http://blog.csdn.net/pipisorry/article/details/39083281 问题: 1. 一个由N个整数元素的一维数组,求其所有子数组中元素和的最大值. 2. 如果数组首尾相邻,也就是允许子数组A[i],...,A[n-1],A[0],...,A[j]存在,求其所有子数组总元素和的最大值. 解法1: /* O(n^2) 遍历算法 */ static int maxSubarraySum1(int *a,int a_len){ int max_sum = INT