求某个数组里连续子数组最大和的几个算法
来源:互联网 发布:windows10 node sass 编辑:程序博客网 时间:2024/06/03 15:18
注意:这里的数组元素,有可能全为负。这样,所谓的:
int find_max_array(const vector<int> &a) { int max_sum = 0; int this_sum = 0; for (int i = 0; i < a.size(); ++i) { this_sum += a[i]; if (this_sum > max_sum) max_sum = this_sum; else if (this_sum < 0) this_sum = 0; } return max_sum; }这种方法就行不通了。下面是几种无论正负的通用方法。
1. 问题描述
输入一个整形数组,求数组中连续的子数组使其和最大。比如,数组x
应该返回 x[2..6]的和187.
2. 问题解决
我们很自然地能想到穷举的办法,穷举所有的子数组的之和,找出最大值。
穷举法
i, j的for循环表示x[i..j],k的for循环用来计算x[i..j]之和。
maxsofar = 0for i = [0, n) for j = [i, n) sum = 0 for k = [i, j] sum += x[k] /* sum is sum of x[i..j] */ maxsofar = max(maxsofar, sum)
有三层循环,穷举法的时间复杂度为
对穷举法的改进1
我们注意到x[i..j]之和 = x[i..j-1]之和 + x[j]
,因此在j的for循环中,可直接求出sum。
maxsofar = 0for i = [0, n) sum = 0 for j = [i, n) sum += x[j] /* sum is sum of x[i..j] */ maxsofar = max(maxsofar, sum)
显然,改进之后的时间复杂度变为
对穷举法的改进2
在计算fibonacci数时,应该还有印象:用一个累加数组(cumulative array)记录前面n-1次之和,计算当前时只需加上n即可。同样地,我们用累加数组cumarr记录:cumarr[i] = x[0] + . . . +x[i]
,那么x [i.. j]之和 = cumarr[j] -cumarr[i - 1]
。
cumarr[-1] = 0for i = [0, n) cumarr[i] = cumarr[i-1] + x[i] maxsofar = 0for i = [0, n) for j = [i, n) sum = cumarr[j] - cumarr[i-1] /* sum is sum of x[i..j] */ maxsofar = max(maxsofar, sum)
时间复杂度依然为
分治法
所谓分治法,是指将一个问题分解为两个子问题,然后分而解决之。具体步骤如下:
先将数组分为两个等长的子数组a, b;
分别求出两个数组a,b的连续子数组之和;
还有一种情况(容易忽略):有可能最大和的子数组跨越两个数组;
最后比较
ma ,mb ,mc ,取最大即可。
在计算从中间元素开始往左累加的最大值 + 从中间元素开始往右累加的最大值
。
float maxsum3(l, u) if (l > u) /* zero elements */ return 0 if (l == u) /* one element */ return max(0, x[l]) m = (l + u) / 2 /* find max crossing to left */ lmax = sum = 0 for (i = m; i >= l; i--) sum += x[i] lmax = max(lmax, sum) /* find max crossing to right */ rmax = sum = 0 for i = (m, u] sum += x[i] rmax = max(rmax, sum) return max(lmax+rmax, maxsum3(l, m), maxsum3(m+1, u));
容易证明,时间复杂度为
动态规划
Kadane算法又被称为扫描法,为动态规划(dynamic programming)的一个典型应用。我们用DP来解决最大子数组和问题:对于数组
子数组最大和即为
Python实现如下:
def max_subarray(A): max_ending_here = max_so_far = A[0] for x in A[1:]: max_ending_here = max(x, max_ending_here + x) max_so_far = max(max_so_far, max_ending_here) return max_so_far
max_ending_here
对应于标记max_so_far
记录已扫描到的子数组的最大和。Kadane算法只扫描了一遍数组,因此时间复杂度为
3. 参考资料
[1] Jon Bentley, Programming Pearls.
[2] GeeksforGeeks, Largest Sum Contiguous Subarray.
转载自:https://www.cnblogs.com/en-heng/p/3970231.html
- 求某个数组里连续子数组最大和的几个算法
- 算法:求连续子数组的最大和
- [算法]求最大连续子数组和的PHP程序
- 【算法】求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- Can't connect to local MySQL server through socket '/tmp/mysql.sock'
- 12.springboot使用redis的订阅功能实现消息队列
- 新建maven一直加载缓存 C:\Users\Administratol\AppData\Local\Temp\..
- 设计模式之禅PK之行为类1
- 51Nod-1050-循环数组最大子段和
- 求某个数组里连续子数组最大和的几个算法
- unity 4.x 全屏
- NOIP2008-03-传纸条
- socket
- demon14.4-14.5
- 写在年末 the end of 2017
- jQuery快速入门基础教程之效果(三)
- mysql命令行客户端快速建立数据库
- 我明白了为什么马云每天穿一样的衣服,踩一双破布鞋,娶一个不漂亮的老婆!