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);
};