Python 由(至少)k个元素分隔的列表元素的最大总和
给定一个数字列表,以查找时间复杂度为o(n)且空间复杂度为o(1)的非相邻元素的最大和,我可以使用以下方法: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是两
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]