[英]finding maximum sum of a disjoint sequence of an array
问题来自: https : //www.hackerrank.com/contests/epiccode/challenges/white-falcon-and-sequence 。 访问链接以获取参考。
我有一个整数序列(-10 ^ 6到10 ^ 6)A。我需要选择A的两个连续的不相交的子序列,假设x和y的大小相同,即n。
之后,您将计算由∑x(i)y(n−i+1)
(1索引)给出的总和
而且我必须选择x和y,以使总和最大化。
Eg:
Input:
12
1 7 4 0 9 4 0 1 8 8 2 4
Output: 120
Where x = {4,0,9,4}
y = {8,8,2,4}
∑x(i)y(n−i+1)=4×4+0×2+9×8+4×8=120
现在,我正在考虑的方法是在O(n ^ 2)行中进行如下操作:
l = 0
和r = N-1
。 在此, N
是数组的大小。 l=0
,我将计算总和,而(l<r)
基本上是指将从数组中第0个位置开始的子序列。 然后,我将递增l
并递减r
,以得出从上述位置+ 1开始并在右侧从right-1
开始的子序列。 有什么更好的方法可以使用吗? 还有效率更高的吗? 我想到了排序,但是我们不能对数字进行排序,因为那样会改变数字的顺序。
为了回答这个问题,我们首先将子序列x从位置i开始时,对于子数组A [i ... j],将S(i,j)定义为两个子序列项相乘的最大和,子序列y终止于位置j。
例如,如果A = [1 7 4 0 9 4 0 1 8 8 2 4],则S(1,2)= 1 * 7 = 7和S(2,5)= 7 * 9 + 4 * 0 = 63。
计算S的递归规则为:S(i,j)= max(0,S(i + 1,j-1)+ A [i] * A [j]),结束条件为S(i, j)= 0,如果i> = j。
对于i = 1..N,j = 1..N的所有组合,请求的最终答案只是S(i,j)的最大值,因为S(i,j)值之一将对应于最大值x,y子序列,因此将等于整个数组的最大值。 使用动态编程计算所有这些S(i,j)值的复杂度为O(N ^ 2),因为在计算S(i,j)的过程中,我们还将计算最多N个其他S(i)的值',j')值,但最终每个组合仅计算一次。
def max_sum(l):
def _max_sub_sum(i, j):
if m[i][j]==None:
v=0
if i<j:
v=max(0, _max_sub_sum(i+1, j-1)+l[i]*l[j])
m[i][j]=v
return m[i][j]
n=len(l)
m=[[None for i in range(n)] for j in range(n)]
v=0
for i in range(n):
for j in range(i, n):
v=max(v, _max_sub_sum(i, j))
return v
警告:此方法假定数字为非负数,因此,现在已经弄清允许输入为负值,此解决方案无法解决海报的实际问题。
假设数字始终为非负数,则在给定相遇的位置时,始终最好使序列尽可能宽。
通过对i的所有值求和,我们可以将和变成标准卷积。 这会产生两倍于预期结果的结果(因为我们同时得到x与y的乘积,以及y与x的乘积),但是我们可以在最后除以2得到原始答案。
现在,您正在尝试寻找信号与其自身的卷积最大值。 有一种执行此操作的标准方法,即使用快速傅立叶变换。 一些库将内置此库,例如在Scipy中有fftconvolve 。
请注意,您不允许重用中心值(例如,对于序列1,3,2,我们不能将x 1,3和y 3,1设为0),因此我们需要检查卷积输出的替代值。
我们现在可以通过以下方式在Python中计算答案:
import scipy.signal
A = [1, 7, 4, 0, 9, 4, 0, 1, 8, 8, 2, 4]
print max(scipy.signal.fftconvolve(A,A)[1::2]) / 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.