繁体   English   中英

查找数组的不相交序列的最大和

[英]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)行中进行如下操作:

  1. 初始化两个变量l = 0r = N-1 在此, N是数组的大小。
  2. 现在,对于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

警告:此方法假定数字为非负数,因此,现在已经弄清允许输入为负值,此解决方案无法解决海报的实际问题。

绝招1

假设数字始终为非负数,则在给定相遇的位置时,始终最好使序列尽可能宽。

把戏2

通过对i的所有值求和,我们可以将和变成标准卷积。 这会产生两倍于预期结果的结果(因为我们同时得到x与y的乘积,以及y与x的乘积),但是我们可以在最后除以2得到原始答案。

绝招3

现在,您正在尝试寻找信号与其自身的卷积最大值。 有一种执行此操作的标准方法,即使用快速傅立叶变换。 一些库将内置此库,例如在Scipy中有fftconvolve

Python代码

请注意,您不允许重用中心值(例如,对于序列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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM