Algorithm 整数数组中最大和的子序列

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

给定一个整数数组,如何找到两个索引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 = 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;
}