这是一个面试问题。给定一个整数数组,找到一个子序列(不一定是连续的),其元素总和的绝对值最小化。
看起来像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}}很容易找到具有其元素的最小绝对值的子序列。
有意义吗?
答案 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。