具有最小绝对值的子序列

时间:2013-03-11 16:21:12

标签: arrays algorithm dynamic-programming

这是一个面试问题。给定一个整数数组,找到一个子序列(不一定是连续的),其元素总和的绝对值最小化。

看起来像DP问题。

  • S1[i]是以a[i]结尾的子序列,其总和> 0和 abs (和)被最小化。

  • S2[i]是以a[i]结尾的子序列,其总和< 0和 abs (和)被最小化。

  • 如果S1[i]>
  • S1[j] + a[i]j < i S1[j] + a[i]的最低值a[i] 0&amp;&amp; S2[i]&lt; 0

  • S2[j] + a[i]j < i S2[j] + a[i]的所有a[i]的最小值S1[i] 0&amp;&amp; S2[i]&gt; 0

对于所有索引,我们现在{{1}}和{{1}}很容易找到具有其元素的最小绝对值的子序列。

有意义吗?

3 个答案:

答案 0 :(得分:2)

我假设你想要非空子序列中的最小绝对和。 (否则如评论中所述,空子序列的总和为0.)

由于元素的顺序无关紧要,你的问题只是问:给定一组(多)元素,所有子集中的最小绝对和是多少。很容易看出subset sum problem减少了这个问题。由于子集和是NP难的所以这个问题。因此,您的多项式时间算法是错误的,这是一个不错的选择。否则,P = NP。

事实上,算法的一个反例是输入序列{-1,2,-2}。

子集求和问题的

Standard approaches可用于获得问题的伪多项式时间算法。

答案 1 :(得分:1)

我希望我能按照你的推理,但我有点慢......你也要求DP和这里的Haskell ......但这是你的意思吗?

import Data.List (sortBy, subsequences)
import Data.Ord (comparing)

minValSub xs = 
  head $ sortBy (comparing snd) 
  $ map (\x -> (x, abs (sum x)) ) (filter (not . null) $ subsequences xs)


OUTPUT:
*Main> minValSub [1,2,3,-4,5]
([1,3,-4],0)

答案 2 :(得分:1)

我假设非空结果集。

让整数列表为S.考虑其中最小的绝对值S [k]。如果S [K] == 0则返回。此外,目标是找到小于S [K]的值。

如你所提到的SP(非负)和SN,将整数除以两组正负整数。现在找到SP中的和,它与SN中的另一个和接近的值小于S [K]。这可以通过在绝对值上分别对SP和SN中的元素进行排序来完成,在每个列表上保持总和和头指针。您可以填写详细信息。

这可能会给出小于S [K]的东西,否则报告S [K]。

例如: S = {1,-4,2,-8,5,-7} k = 0,S [k] = 1

SP(已排序)= {1,2,5} SN(已排序)= {-4,-7,-8}

同时遍历两个数组,你可以得到一些候选{1,2}和{-4},它们将得到与S [k]相同的结果。但{2,5}和{-7}会更好,净和为0。