Algorithm 整数数组中最大和的子序列
给定一个整数数组,如何找到两个索引i和j,从而使子数组中从索引开始和结束的元素之和在线性时间内最大化。假设您得到了数组Algorithm 整数数组中最大和的子序列,algorithm,arrays,language-agnostic,Algorithm,Arrays,Language Agnostic,给定一个整数数组,如何找到两个索引i和j,从而使子数组中从索引开始和结束的元素之和在线性时间内最大化。假设您得到了数组a。首先,计算数组s,其中s[i]=a[0]+a[1]+…+a[i]。您可以在线性时间内完成: s[0]=a[0]; for (i=1;i<N;i++) s[i]=s[i-1]+a[i]; 迭代每个数组元素并将其与min进行比较。。。但在每次迭代中,该min是数组中的最低值,其中索引范围为0..j!这就是我们要找的 global_max = a[0]; max_i = m
a
。首先,计算数组s
,其中s[i]=a[0]+a[1]+…+a[i]
。您可以在线性时间内完成:
s[0]=a[0];
for (i=1;i<N;i++) s[i]=s[i-1]+a[i];
迭代每个数组元素并将其与min
进行比较。。。但在每次迭代中,该min
是数组中的最低值,其中索引范围为0..j
!这就是我们要找的
global_max = a[0];
max_i = max_j = 0;
local_min_index = 0;
for (j=1; j<N; j++){
// here local_min is the lowest value of s[i], where 0<=i<j
if (s[j] - s[local_min_index] > global_max) {
global_max = s[j] - s[local_min_index]
//update indices
max_i = local_min_index + 1;
max_j = j;
}
//update local_min_index for next iteration
if (s[j]<local_min){
local_min = s[j];
// update indices
local_min_index = j;
}
}
global_max=a[0];
max_i=max_j=0;
局部最小指数=0;
对于(j=1;j,从我的副本:
这个python代码返回序列的边界。对于原始问题,i=bestlo
,j=besthi-1
#
# given a sequence X of signed integers,
# find a contiguous subsequence that has maximal sum.
# return the lo and hi indices that bound the subsequence.
# the subsequence is X[lo:hi] (exclusive of hi).
#
def max_subseq(X):
#
# initialize vars to establish invariants.
# 1: best subseq so far is [bestlo..besthi), and bestsum is its sum
# 2: cur subseq is [curlo..curhi), and cursum is its sum
#
bestlo,besthi,bestsum = 0,0,0
curlo,curhi,cursum = 0,0,0
for i in xrange(len(X)):
# extend current subseq and update vars
curhi = i+1
cursum += X[i]
if cursum <= 0:
#
# the current subseq went under water,
# so it can't be usefully extended.
# start fresh at next index.
#
curlo = curhi
cursum = 0
elif cursum > bestsum:
# adopt current subseq as the new best
bestlo,besthi,bestsum = curlo,curhi,cursum
return (bestlo,besthi)
实际上,您需要修改Kadane的算法,记住子数组的上下限,下面是C++11代码:
#include <iostream>
#include <vector>
typedef std::pair<std::vector<int>::iterator, std::vector<int>::iterator> SubSeq;
SubSeq getMaxSubSeq(std::vector<int> &arr) {
SubSeq maxSequence{arr.begin(), arr.begin()};
auto tmpBegin = arr.begin();
int maxEndingHere = 0;
int maxSoFar = 0;
for(auto it = arr.begin(); it < arr.end(); ++it) {
int currentSum = maxEndingHere + *it;
if(currentSum > 0) {
if(maxEndingHere == 0) {
tmpBegin = it;
}
maxEndingHere = currentSum;
} else {
maxEndingHere = 0;
}
if(maxEndingHere > maxSoFar) {
maxSoFar = maxEndingHere;
maxSequence.first = tmpBegin;
maxSequence.second = it + 1;
}
}
return maxSequence;
}
int main()
{
std::vector<int> arr{-1, 2, 90, -50, 150, -300, 56, 12};
auto seq = getMaxSubSeq(arr);
while(seq.first != seq.second) {
std::cout << *(seq.first) << " ";
++(seq.first);
}
return 0;
}
#包括
#包括
typedef std::pair SubSeq;
SubSeq getMaxSubSeq(标准::向量和arr){
SubSeq maxSequence{arr.begin(),arr.begin()};
自动tmpBegin=arr.begin();
int maxEndingHere=0;
int maxSoFar=0;
用于(自动it=arr.begin();it0){
如果(maxEndingHere==0){
tmpBegin=it;
}
maxEndingHere=当前总和;
}否则{
maxendingher=0;
}
如果(maxEndingHere>maxSoFar){
maxSoFar=maxEndingHere;
maxSequence.first=tmpBegin;
maxSequence.second=it+1;
}
}
返回maxSequence;
}
int main()
{
std::载体arr{-1,2,90,-50,150,-300,56,12};
自动顺序=getMaxSubSeq(arr);
while(顺序第一!=顺序第二){
std::你的意思是-在索引之间?i=0
和j=array.length-1
:)@Bart,谁说数组元素大于零?到目前为止,答案似乎假设你的意思是“从索引i到索引j的元素之和”,但据我所知,你只要求元素i和j的和,请详细说明?(也可以i==j吗?在这种情况下,答案将是2*max(数组值)
:-)两个元素的总和。还有一个负元素是正确的,一个简洁的。但是你花了和我同样的时间来复制它:)那么,i
和j
是什么呢?值得一提的是,这实际上被称为卡丹算法;发现了(或发明了,无论你的船在哪里)1984年由卡内基梅隆大学的杰伊·卡丹(Jay Kadane)提出。这是唯一已知的解决此问题的线性时间算法,通常称为。当输入数组的所有值均为negative@jillesdewit,在子序列中,元素不一定是连续的。例如:在数组中[1,2,3,4,5][2,3,4]是子数组,而[1,3,5]是一个匿名用户解释代码中的错误的冗长帖子的子序列。我去掉了它们,除非N==0
失败。
#
# given a sequence X of signed integers,
# find a contiguous subsequence that has maximal sum.
# return the lo and hi indices that bound the subsequence.
# the subsequence is X[lo:hi] (exclusive of hi).
#
def max_subseq(X):
#
# initialize vars to establish invariants.
# 1: best subseq so far is [bestlo..besthi), and bestsum is its sum
# 2: cur subseq is [curlo..curhi), and cursum is its sum
#
bestlo,besthi,bestsum = 0,0,0
curlo,curhi,cursum = 0,0,0
for i in xrange(len(X)):
# extend current subseq and update vars
curhi = i+1
cursum += X[i]
if cursum <= 0:
#
# the current subseq went under water,
# so it can't be usefully extended.
# start fresh at next index.
#
curlo = curhi
cursum = 0
elif cursum > bestsum:
# adopt current subseq as the new best
bestlo,besthi,bestsum = curlo,curhi,cursum
return (bestlo,besthi)
r'''
doctest examples:
>>> print max_subseq([])
(0, 0)
>>> print max_subseq([10])
(0, 1)
>>> print max_subseq([-1])
(0, 0)
>>> print max_subseq(xrange(5))
(1, 5)
>>> print max_subseq([-1, 1, -1])
(1, 2)
>>> print max_subseq([-1, -1, 1, 1, -1, -1, 1, 2, -1])
(6, 8)
>>> print max_subseq([-2, 11, -4, 13, -5, -2])
(1, 4)
>>> print max_subseq([4, -3, 5, -2, -1, 2, 6,-4])
(0, 7)
'''
#include <iostream>
#include <vector>
typedef std::pair<std::vector<int>::iterator, std::vector<int>::iterator> SubSeq;
SubSeq getMaxSubSeq(std::vector<int> &arr) {
SubSeq maxSequence{arr.begin(), arr.begin()};
auto tmpBegin = arr.begin();
int maxEndingHere = 0;
int maxSoFar = 0;
for(auto it = arr.begin(); it < arr.end(); ++it) {
int currentSum = maxEndingHere + *it;
if(currentSum > 0) {
if(maxEndingHere == 0) {
tmpBegin = it;
}
maxEndingHere = currentSum;
} else {
maxEndingHere = 0;
}
if(maxEndingHere > maxSoFar) {
maxSoFar = maxEndingHere;
maxSequence.first = tmpBegin;
maxSequence.second = it + 1;
}
}
return maxSequence;
}
int main()
{
std::vector<int> arr{-1, 2, 90, -50, 150, -300, 56, 12};
auto seq = getMaxSubSeq(arr);
while(seq.first != seq.second) {
std::cout << *(seq.first) << " ";
++(seq.first);
}
return 0;
}