我有W
0..N-1
我需要将它们分成两组:说K
和N-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)
之间的差异最大。
答案 0 :(得分:2)
编辑:请注意,在您发布的问题中,您似乎期望排序从高到低排序。 std::sort
和std::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)