ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

剑指offer.42-连续子数组的最大和

2021-09-18 10:30:22  阅读:176  来源: 互联网

标签:最大 5C% 20% 连续 数组 data maxSum offer.42


题目:输入一个整型数组,数组里有正数和负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。例如输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18。

不管暴力枚举适不适合解题,我们都可以先分析一下它的时间复杂度。一个长度为n的数组,共有n(n+1)/2个子数组,所以要找出所有子数组中的最大的和值,需要O(n^2)的时间复杂度,不满足题目需求。往往最直观的解不是最优解

那我们看看动态规划是否可以呢?

这题很明显可以分解成子问题,设f(i)是以第i个数字结尾的子数组最大和,要想求得f(i)的最大和,我们肯定需要先求的f(i-1)的最大和...依次思路,现在的问题就变成了:当知道f(i-1)的最大和后,f(i)的最大和该是多少?

分析:假设有长度为n的数组data,如果f(i-1)的最大和是小于零的,那么加上f(i)后的值肯定是小于f(i-1),那此时f(i)的最大和应该等于data[i];如果f(i-1)的最大和是大于零的,那么加上f(i)后的值肯定是大于data[i]的,所以此时f(i)的最大和应该等于f(i-1)+data[i]

经过分析,我们可以得到下面的公式:

f(i)= \begin{cases} data[i] & i=0 || f(i-1)<=0 \\ f(i-1)+data[i] & i>0 \&\& f(i-1)>0 \\ \end{cases}

通过上面的公式,我们可以得到一系列的最大和,剩下的操作就是从这些和中找出最大的和即可。

代码如下:

public Integer findGreatestSumOfSubArray(int[] data) {
    if (data == null || data.length == 0) return null;

    int result = 0;
    int[] maxSum = new int[data.length]; // 辅助数组,记录以第i个数字结尾的子数组最大和
    for(int i = 0; i < data.length; i++) {
        if (i > 0 && maxSum[i-1] > 0) {
            maxSum[i] = maxSum[i-1] + data[i];
        } else {
            maxSum[i] = data[i];
        }
        result = result > maxSum[i] ? result : maxSum[i]; // 循环中顺带判断出最大值
    }

    return result;
}

只需要遍历一次data数组,所以时间复杂度为O(n),满足题目要求。

标签:最大,5C%,20%,连续,数组,data,maxSum,offer.42
来源: https://blog.csdn.net/qq_38058241/article/details/120322474

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有