Reputation:
I have an array W
of 0..N-1
I need to split them into two sets: Say K
and N-K
elements.
But the condition is: sum(N-K)
- sum(K)
should be maximum.
How do I approach this?
I tried doing this:
Sort the array - std::sort(W,W+N)
, and then:
for(int i=0; i<K; ++i) less+=W[i];
for(int i=K; i<N; ++i) more+=W[i];
And then more-less
But I don't think this is the optimum way, or it may even be wrong for some of the cases.
Thanks.
UPDATE:
We have to choose K
elements from W
such that difference betweensum(k elements)
and sum(remaining elements)
is maximum.
Upvotes: 2
Views: 922
Reputation: 63755
Edit: Note that in your posted question, you seem to be expecting sort to sort from high-to-low. Both std::sort
and std::nth_element
put the low elements first. I have replaced K
with (N-K)
in the answer below to correct that.
Edit after UPDATE: Do the below twice, once for K
and once for (N-K)
. Choose the optimal answer.
More optimal than std::sort
would be std::nth_element
for your purposes.
std::nth_element( W, W+(N-K), W+N );
Your use of std::sort
will use O(n log n) complexity to order all the elements within both your sets, which you don't need.
std::nth_element
will use O(n) complexity to partition without completely sorting.
Note: your for loops may also be replaced with std::accumulate
less = std::accumulate( W, W+(N-K), 0 );
more = std::accumulate( W+(N-K), W+N, 0 );
Upvotes: 2
Reputation: 3254
It can be done using max heap
. O(n + n log k)
time
Make a max heap of size k
. We have find the lowest k
elements of the array. The root
of heap will be the highest element in the heap. Make a heap of first k elements
.
Now iterate through the array. Compare the array element with the root
of max heap. If it is smaller than root then replace it and heapify the heap again. This will take O(n log k) time.
Find the sum of elements of heap.
Now you can find the sum of rest of the elements of array and get the difference. (O(n)
) time
Total time O(n + n log k)
EDIT: Perhaps you can find the sum of all elements of array while traversing it for heap. This will save O(n)
time and it can be solved in O(n log k)
Upvotes: 0
Reputation: 33506
You are to split the set of elements into two distinctive nonoverlapping subsets A and B. You want the sum(A)-sum(B) be as high as possible.
Therefore, you want the sum(A) be as high as possible and sum(B) as low as possible.
Therefore, the set 'A' should contain as high elements as possible
and the set 'B' should contain as low elements as possible
By sorting the input set by element's value, and by assigning 'lowest elements' to B and 'highest elements' to A, you are guaranteed that the sum(A)-sum(B) will be max possible.
I do not see any cases where your approach would be wrong.
As to the 'being optimal' things, I did not analyze it at all. Drew's note seems quite probable.
Upvotes: 2