精确k个元素的最小非连续序列

时间:2016-11-23 05:47:43

标签: algorithm

我遇到的问题可以简化为:

  

给定N个正数的数组,找到具有最小和的精确K元素的非连续序列。

     

好的:只报告总和。奖励:可以识别拾取的元素(至少有一组索引,如果很多可以实现相同的总和)。

(以外行人的术语:从N值中挑选任何K 非相邻元素,使其总和最小)

当然,2*K <= N+1(否则无法解决),问题对正/负不敏感(只需将数组值移至MIN=min(A...),然后将K*MIN添加回K+2回答)。

到目前为止(天真的方法):

  1. 选择最接近最小值的K=2索引。我不确定这一点,因为K>2这似乎是涵盖所有特定案例的必要条件,但我不知道K+2 **是否需要/足够
  2. 蛮力从指标值得到的最小值与非邻接标准的上一步结果 - 如果我是对的并且(K+1)*(K+2)就足够了,我可以强制执行K+2解决方案空间,但正如我所说。我不确定K>2对于2*K是否足够(如果事实上C(2*K, K)点是必要的,那么暴力破坏会超出窗口 - 二项式系数K=2过度增长快)
  3. 如何以最小的时间/空间复杂度完成这项工作的任何聪明的想法?

    对于[4,1,0,1,4,3,4]

    ** ,这是一个非常重要的例子,其中最接近绝对最小值的4个值是选择目标总和0所必需的 - 一个不能使用{ {1}}用于构建最小和的值,因为它打破了非连续性标准。

    PS - 如果您想要显示代码片段,C / C ++和/或Java将会受到赞赏,但任何具有良好语法或伪代码的语言都会做(我认为“体面的语法”不包括Perl,不会不是吗?)

2 个答案:

答案 0 :(得分:3)

假设输入数字存储在数组a [N]

通用方法是DP:f(n,k)= min(f(n-1,k),f(n-2,k-1)+ a [n])

需要O(N * K)时间并有2个选项:

  • 用于懒惰回溯递归解O(N * K)空间
  • 用于正向循环的O(K)空间

在大K的特殊情况下,还有另一种可能性:

  • 使用递归反向追踪
  • 代替N * K尺寸的辅助数组使用地图(n,地图(k,对(答案,列表(答案索引))))
  • 保存答案和此答案的索引列表
  • 如果k> N / 2 ,
  • 立即返回MAX_INT

这样,对于K~ = N / 2,你的时间比O(N K)更低,类似于O(N log(N))。对于小K,它将增加到O(N * log(N) K log(K)),因此一般方法或特殊情况算法之间的决定很重要。

答案 1 :(得分:2)

应该采用动态编程方法。

从左到右沿阵列工作。在每个点i,对于来自1..k的j的每个值,找到从1..i中挑选j个非连续元素的正确答案的值。您可以通过查看i-1,i-2的答案和array [i]的值来计算出答案。你想要的答案是n的答案,长度为n的数组。完成此操作后,您应该能够通过沿阵列的反向跟踪来确定元素是什么,以确定每个点的最佳决策是否涉及在该点选择数组元素,因此是否使用数组[i -1] [k]或数组[i-2] [k-1]。