Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 由(至少)k个元素分隔的列表元素的最大总和_Python_Algorithm_Dynamic Programming - Fatal编程技术网

Python 由(至少)k个元素分隔的列表元素的最大总和

Python 由(至少)k个元素分隔的列表元素的最大总和,python,algorithm,dynamic-programming,Python,Algorithm,Dynamic Programming,给定一个数字列表,以查找时间复杂度为o(n)且空间复杂度为o(1)的非相邻元素的最大和,我可以使用以下方法: sum1= 0 sum2= list[0] for i in range(1, len(list)): num= sum1 sum1= sum2+ list[i] sum2= max(num, sum2) print(max(sum2, sum1)) 只有当k=1[求和数字之间只有一个元素]时,此代码才会工作。如何通过使用动态规划更改k值来改善它。其中k是两

给定一个数字列表,以查找时间复杂度为o(n)且空间复杂度为o(1)的非相邻元素的最大和,我可以使用以下方法:

sum1= 0
sum2= list[0]

for i in range(1, len(list)):
    num= sum1
    sum1= sum2+ list[i]
    sum2= max(num, sum2)

print(max(sum2, sum1))
只有当k=1[求和数字之间只有一个元素]时,此代码才会工作。如何通过使用动态规划更改k值来改善它。其中k是两个求和数之间的元素数。 例如:

列表=[5,6,4,1,2]k=1 答案=11#5+4+2

列表=[5,6,4,1,2]k=2 答案=8#6+2

列表=[5,3,4,10,2]k=1 答案=15#5+10编辑: 我误解了这个问题,如果你需要至少有k个元素,那么下面是一个
O(n^2)
解决方案

如果数字为非负,则DP循环关系为:

DP[i] = max (DP[j] + A[i]) For all j st 0 <= j < i - k 
      = A[i] otherwise.

DP[i]=max(DP[j]+A[i])对于所有j st0可以用空间O(k)和时间O(nk)来解决这个问题。如果k是一个常数,这符合你问题中的要求

该算法从位置k+1循环到n。(如果数组短于此,显然可以在O(k)中求解)。在每一步中,它都会维护一个长度为k+1的数组
best
,使得
best
的第j个条目是迄今为止找到的最佳解决方案,这样它使用的最后一个元素至少在当前位置的左边j处

初始化
best
是通过为其条目j设置数组中位于位置1、…、k+1-j的最大非负条目来完成的。例如,
best[1]
是位置1、…、k中最大的非负项,
best[k+1]
为0

当位于数组的位置i时,是否使用元素i。如果使用它,到目前为止相关的
best
best[1]
,所以写
u=max(best[1]+a[i],best[1])
。如果未使用元素i,则每个“至少”部分移动一个,因此对于j=2,…,k+1,
best[j]=max(best[j],best[j-1])
。最后,设置
最佳[1]=u


在算法结束时,解决方案是
best

中最大的项目。虽然不确定复杂性,但编码效率让我失望

max([sum(l[i::j]) for j in range(k,len(l)) for i in range(len(l))])

(我用
l
替换了
list
变量,以避免踩到关键字)。

以下是Ami Tavory描述的算法的快速实现(据我所知)。它应该适用于任何序列,但如果列表都是负数,则最大和将是
0
(空子序列的和)

这使用
O(k)
空间和
O(N)
时间。所有
deque
操作都是
O(1)
,包括在一端追加一个值(并隐式从另一端删除一个值,以保持长度限制)


如果希望算法返回最大子序列(而不仅仅是其总和),可以将
deque
的初始化更改为以空列表开始,而不是
0
,然后在循环体中追加
max([item]+best[-1],best[0],key=sum)
。不过,这样的效率会低一些,因为它会在所有地方添加
O(N)
操作。

当我运行代码时,得到的是13而不是11。我看不出它是如何强制在被求和的数字之间至少有一个数字。所有数字都是非负的吗?非常感谢,你的方法是正确的,但例如,如果k=1,它将始终求和,因为它们之间有一个不同,因为在其他情况下,如果我们在它们之间留出一个以上的空间,就可能得到更高的和。对不起,也许我的问题不是很清楚,我应该写“求和数之间至少有k个元素”。我只是编辑了这个问题,这是错误的。它只是检查不同起始位置的等距子序列和等距跳转。最佳子序列不一定具有等距跳转。如何显示最大子序列的索引,而不是值。
max([sum(l[i::j]) for j in range(k,len(l)) for i in range(len(l))])
import collections

def max_sum_separated_by_k(iterable, k):
    best = collections.deque([0]*(k+1), k+1)
    for item in iterable:
        best.appendleft(max(item + best[-1], best[0]))
    return best[0]