拆分阵列分为两组?

时间:2013-04-08 09:01:20

标签: c++ arrays algorithm stl

我有W

的数组0..N-1

我需要将它们分成两组:说KN-K元素。

但条件是:sum(N-K) - sum(K)应该是最大值。

我该如何处理?

我试过这样做: 对数组进行排序 - std::sort(W,W+N),然后:

for(int i=0; i<K; ++i) less+=W[i];
for(int i=K; i<N; ++i) more+=W[i];

然后more-less

但我不认为这是最佳方式,或者某些情况甚至可能是错误的。

感谢。

更新

我们必须从K中选择W元素,以使sum(k elements)sum(remaining elements)之间的差异最大。

3 个答案:

答案 0 :(得分:2)

编辑:请注意,在您发布的问题中,您似乎期望排序从高到低排序。 std::sortstd::nth_element都将低位元素放在第一位。我已在下面的答案中将K替换为(N-K)以更正此问题。

更新后修改:执行以下操作两次,一次针对K,一次针对(N-K)。选择最佳答案。

std::sort更优化std::nth_element用于您的目的。

std::nth_element( W, W+(N-K), W+N );

您对std::sort的使用将使用O(n log n)复杂度来排序您不需要的两个集合中的所有元素。

std::nth_element将使用O(n)复杂度来 partition ,而不会完全排序。

注意:您的for循环也可以替换为std::accumulate

less = std::accumulate( W, W+(N-K), 0 );
more = std::accumulate( W+(N-K), W+N, 0 );

答案 1 :(得分:2)

您要将元素集拆分为两个不同的非重叠子集A和B.您希望总和(A)-sum(B)尽可能高。

因此,您希望总和(A)尽可能高,总和(B)尽可能低。

因此,集合'A'应包含尽可能高的元素
并且集合'B'应包含尽可能低的元素

通过按元素的值对输入集进行排序,并通过将“最低元素”分配给B和“最高元素”到A,可以保证总和(A)-sum(B)最大可能。

我认为你的方法没有错。

关于'最优'的事情,我根本没有分析它。德鲁的笔记似乎很可能。

答案 2 :(得分:0)

可以使用max heap完成。 O(n + n log k)时间

制作一个大小为k的最大堆。我们找到了数组中最低的k元素。堆的root将是堆中的最高元素。 Make a heap of first k elements

现在遍历数组。将数组元素与max heap的root进行比较。如果它小于root,则替换它并再次堆积堆。这将花费O(n log k)时间。 找到堆的元素总和。

现在你可以找到数组其余元素的总和并获得差异。 (O(n))时间

总时间O(n + n log k)

编辑:也许你可以在遍历堆时找到数组的所有元素的总和。这将节省O(n)时间,可以在O(n log k)

中解决