Python 最大和子列表?

Python 最大和子列表?,python,algorithm,Python,Algorithm,我对这个问题感到困惑,因为它想问什么 写入函数mssl()(最小和子列表),将列表作为输入 整数的数目。然后计算并返回最大和的总和 输入列表的子列表。最大和子列表是一个子列表 输入列表的(切片),其条目之和最大。空的 子列表定义为总和为0。例如,最大和子列表 列表中的[4,-2,-8,5,-2,7,7,2,-6,5]是[5,-2,7,7,2] 其条目的总和为19 如果我使用这个函数,它应该返回类似于 >>> l = [4, -2, -8, 5, -2, 7, 7, 2, -6,

我对这个问题感到困惑,因为它想问什么

写入函数
mssl()
(最小和子列表),将列表作为输入 整数的数目。然后计算并返回最大和的总和 输入列表的子列表。最大和子列表是一个子列表 输入列表的(切片),其条目之和最大。空的 子列表定义为总和为0。例如,最大和子列表 列表中的
[4,-2,-8,5,-2,7,7,2,-6,5]
[5,-2,7,7,2]
其条目的总和为
19

如果我使用这个函数,它应该返回类似于

>>> l = [4, -2, -8, 5, -2, 7, 7, 2, -6, 5]
>>> mssl(l)
19
>>> mssl([3,4,5])
12
>>> mssl([-2,-3,-5])
0
我怎么做

以下是我当前的尝试,但没有产生预期的结果:

def mssl(x):
    ' list ==> int '
    res = 0
    for a in x:
        if a >= 0:
            res = sum(x)
        return res
    else:
        return 0

它要求你在列表中选择一个较小的部分,使较小部分的总和最大

如果列表都是正数,那么最大和的部分当然就是整个列表的总和,即6

如果列表都是负数
[-1-2-3]
,则具有最大总和的子部分是总和为0的nothing
[]

然而,如果列表中有一些正面的和负面的,那么决策就更难了

[1 2 3-100 3 4 5]
您应该看到
[3 4 5]
并返回12


[1 2 3-2 3 4 5]
您应该使用所有数据并返回16

因此,如果您了解什么是子列表(或片,可以假定为相同的东西),片由开始索引和结束索引定义

因此,您可以尝试迭代所有可能的开始和结束索引,计算相应的和,然后返回最大值


提示:开始索引可以从0到
len(给定列表)-1
。结束索引可以从
start\u index
len(给定的\u列表)-1
。您可以使用嵌套的
for
循环来检查所有可能的组合。

简单的解决方案是迭代列表,然后尝试将切片相加,直到找到最好的一个。这里我还包括了返回实际子列表的选项,默认情况下这是False。为此,我使用defaultdict,因为它比查找更简单

from collections import defaultdict

def mssl(lst, return_sublist=False):
    d = defaultdict(list)
    for i in range(len(lst)+1):
        for j in range(len(lst)+1):
            d[sum(lst[i:j])].append(lst[i:j])
    key = max(d.keys())
    if return_sublist:
        return (key, d[key])
    return key

print mssl([4, -2, -8, 5, -2, 7, 7, 2, -6, 5])
19
print mssl([4, -2, -8, 5, -2, 7, 7, 2, -6, 5], True)
(19, [[5, -2, 7, 7, 2]])
奖励:列表理解方法:

def _mssl(lst):
    return max( sum( lst[i:j] ) for i in xrange(len(lst)+1) for j in xrange(i, len(lst)+1) )

这种区别对OP来说可能并不重要,OP似乎只是想了解如何解决问题,但我认为值得一提:

这里的其他解决方案包括反复总结列表的所有子部分。我们可以通过使用动态规划来避免这些重复求和,因为当然,如果我们已经知道从
i
j
的和,我们就不需要再将它们相加,得到从
i
j+1
的和

也就是说,制作一个部分和的2d数组,以便
partsum[i,j]==sum(lst[i:j])
。类似于(使用字典,因为它更容易索引;numpy数组也同样容易且更高效):


这需要O(n^2)时间和内存,而Lev/Inbar的方法需要O(n^3)时间和O(1)内存(如果没有像Inbar的第一个代码示例那样简单地实现)。

使用动态编程,实际上有一个非常优雅、非常有效的解决方案。它需要O(1)个空间,以及O(n)个时间——这是无与伦比的

A
定义为输入数组(零索引),将
B[i]
定义为所有子列表的最大和,这些子列表以结尾,但不包括位置
i
(即所有子列表
A[j:i]
)。因此,
B[0]=0
B[1]=max(B[0]+A[0],0)
B[2]=max(B[1]+A[1],0)
B[3]=max(B[2]+A[2],0)
,等等。然后,很明显,解决方案是由
max(B[0],…,B[n])
给出的

由于每个
B
值只依赖于前面的
B
,因此我们可以避免存储整个
B
数组,从而为我们提供了O(1)空间保证

通过这种方法,
mssl
简化为一个非常简单的循环:

def mssl(l):
    best = cur = 0
    for i in l:
        cur = max(cur + i, 0)
        best = max(best, cur)
    return best
演示:

>>> mssl([3,4,5])
12
>>> mssl([4, -2, -8, 5, -2, 7, 7, 2, -6, 5])
19
>>> mssl([-2,-3,-5])
0

如果还需要开始和结束切片索引,则需要跟踪更多的信息位(注意,这仍然是O(1)空间和O(n)时间,只是有点毛茸茸的):

这将返回一个元组
(a,b,c)
,使得
sum(l[a:b])==c
c
最大:

>>> mssl([4, -2, -8, 5, -2, 7, 7, 2, -6, 5])
(3, 8, 19)
>>> sum([4, -2, -8, 5, -2, 7, 7, 2, -6, 5][3:8])
19
这是。Kadane的算法可以在
O(n)
时间和
O(1)
空间中求解,其原理如下:

def mssl(x):
    max_ending_here = max_so_far = 0
    for a in x:
        max_ending_here = max(0, max_ending_here + a)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

我假设这是一个问题,在一个数组中找到一个子序列,它产生最大和。我在搜索最大和子集问题时遇到了这个问题

此问题的java实现:

public static int maximumSumSubSequence(int[] array) {

    if (null == array) {
        return -1;
    }

    int maxSum = Integer.MIN_VALUE;
    int startIndexFinal = 0;
    int endIndexFinal = 0;
    int currentSum = 0;
    int startIndexCurrent = 0;

    for (int i = 0; i < array.length; i++) {
        currentSum += array[i];

        if (currentSum > maxSum) {
            maxSum = currentSum;
            endIndexFinal = i;
            startIndexFinal = startIndexCurrent;
        }
        if (currentSum <= 0) {
            currentSum = 0;
            startIndexCurrent = i + 1;
        }
    }
    System.out.println("startIndex: " + startIndexFinal + " endIndex: " + endIndexFinal);
    return maxSum;
}
公共静态int-maximumSumSubSequence(int[]数组){
if(null==数组){
返回-1;
}
int maxSum=Integer.MIN_值;
int startIndexFinal=0;
int-endIndexFinal=0;
int currentSum=0;
int startIndexCurrent=0;
for(int i=0;imaxSum){
最大和=当前和;
endIndexFinal=i;
startIndexFinal=startIndexCurrent;
}

if(currentSum这里有一个Java实现,使用Kadane的算法,它打印最大和的索引。这个实现需要O(n)时间和O(1)空间

publicstaticvoidmaxsumindexes(int[]a){
int size=a.length;
如果(大小==0)返回;
int maxatinex=a[0],max=a[0];
int-bAtIndex=0;
int b=0,e=0;
对于(int i=1;idef mssl(x):
    max_ending_here = max_so_far = 0
    for a in x:
        max_ending_here = max(0, max_ending_here + a)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far
public static int maximumSumSubSequence(int[] array) {

    if (null == array) {
        return -1;
    }

    int maxSum = Integer.MIN_VALUE;
    int startIndexFinal = 0;
    int endIndexFinal = 0;
    int currentSum = 0;
    int startIndexCurrent = 0;

    for (int i = 0; i < array.length; i++) {
        currentSum += array[i];

        if (currentSum > maxSum) {
            maxSum = currentSum;
            endIndexFinal = i;
            startIndexFinal = startIndexCurrent;
        }
        if (currentSum <= 0) {
            currentSum = 0;
            startIndexCurrent = i + 1;
        }
    }
    System.out.println("startIndex: " + startIndexFinal + " endIndex: " + endIndexFinal);
    return maxSum;
}
public static void maxSumIndexes(int[] a) {

    int size = a.length;
    if(size == 0) return;

    int maxAtIndex = a[0], max = a[0];
    int bAtIndex = 0;
    int b = 0, e = 0;

    for(int i = 1; i < size; i++) {
        maxAtIndex = Math.max(a[i], a[i] + maxAtIndex);
        if(maxAtIndex == a[i])
            bAtIndex = i;

        max = Math.max(max, maxAtIndex);
        if(max == maxAtIndex) {
            e = i;
            b = (b != bAtIndex)? bAtIndex : b;
        }
    }

    System.out.println(b);
    System.out.println(e);
}
def mesl(lst):
    sub_sum = list()
    row_sum = list()
    for i in range(len(lst)):
        sub_sum = list()
        sub_sum.append(lst[i])
        k = 1
        for j in range(i+1,len(lst)):
            sub_sum.append(sub_sum[k-1] + lst[j])
            k+=1
        row_sum.append(max(sub_sum))      
    sum = max(row_sum)
    if  sum < 0:
        sum = 0
    return sum
In [21]: def mssl(l):
...:     best = cur = l[0]
...:     for i in range(len(l)):
...:         cur = max(cur + l[i], l[i])
...:         best = max(best, cur)
...:     return best
In [23]: mssl([-6, -44, -5, -4, -9, -11, -3, -99])
Out[23]: -3
In [24]: mssl([-51, -23, -8, -2, -6])
Out[24]: -2
In [30]: mssl([4, -2, -8, 5, -2, 7, 7, 2, -6, 5])
Out[30]: 19
def maxSumSubArr(arr):
    cur_sum = best_sum = arr[0]
    for i in range(1, len(arr)):
        cur_sum = max(arr[i], cur_sum+arr[i])
        best_sum = max(best_sum, cur_sum)
    return best_sum
var maxSubArray = function(nums) {
    for (let i = 1; i < nums.length; i++){
        nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]);
    }
    return Math.max(...nums);
};