问题来自: 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
开始的子序列。 我可以使用更好的方法吗?什么更有效率?我想过排序,但我们不能对数字进行排序,因为这会改变数字的顺序。
答案 0 :(得分:1)
为了回答这个问题,我们首先将S(i,j)定义为多个子序列项的最大和,对于子序列A [i ... j],当子序列x开始时位置i,子序列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 iff 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& #39;,j&#39;)值,但最终每个组合只计算一次。
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
答案 1 :(得分:0)
警告: 这种方法假设数字是非负的,所以这个解决方案没有回答海报的实际问题,现在已经澄清了允许负输入值。
假设数字总是非负数,那么在给定它们相遇的位置的情况下,最好使序列尽可能宽。
我们可以通过对i的所有值求和来将总和更改为标准卷积。这产生了两倍的期望结果(因为我们得到x与y和y与x的乘积),但我们可以在结尾处除以2得到原始答案。
您现在正试图找到信号自身卷积的最大值。有一种标准方法可以使用快速傅立叶变换。一些图书馆将内置这种内容,例如在Scipy中有fftconvolve。
请注意,您不允许重复使用中心值(例如,对于序列1,3,2我们不能使x 1,3和y 3,1)所以我们需要检查替代值卷积输出。
我们现在可以通过以下方式在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