import java.util.Arrays;
import java.util.PriorityQueue;
public class Main {
public static void main
(String[] args
) { int[] array = {1, 2, 1, 3, 1000};
}
private static long[] findSums(int[] array, int k) {
long maxSum
= Arrays.
stream(array
).
filter(it
-> it
>= 0).
sum();
int[] positives
= Arrays.
stream(array
).
filter(it
-> it
>= 0).
sorted().
toArray(); int[] negatives
= Arrays.
stream(array
).
filter(it
-> it
< 0).
sorted().
toArray(); // sort time complexity is O(n*log(n))
PriorityQueue<Long> sums = new PriorityQueue<>(k); // priority queue is implemented using heap so adding element has time complexity O(log(n))
sums.add(maxSum); // we start with max sum - combination of all positive elements
Long[] previousAddedSums
= {};
// iterate over positive values
for (int i = 0; i < positives.length; i++) {
if (positives[i] == previous) {
sumsToIterate = previousAddedSums;
} else {
sumsToIterate
= sums.
toArray(new Long[sums.
size()]); }
previousAddedSums
= new Long[sumsToIterate.
length]; for (int j = 0; j < sumsToIterate.length; j++) {
long newSum = sumsToIterate[j] - positives[i];
// new sum is calculated - value positives[i] is removed from combination (subtracted from sum of that combination)
sums.add(newSum);
previousAddedSums[j] = newSum;
if (sums.size() > k) {
sums.poll(); // only first k maximum sums are needed at the moment
}
}
previous = positives[i];
}
// iterate over negative values in reverse order
for (int i = negatives.length - 1; i >= 0; i--) {
if (negatives[i] == previous) {
sumsToIterate = previousAddedSums;
} else {
sumsToIterate
= sums.
toArray(new Long[sums.
size()]); }
previousAddedSums
= new Long[sumsToIterate.
length]; for (int j = 0; j < sumsToIterate.length; j++) {
long newSum = sumsToIterate[j] + negatives[i]; // value negatives[i] is added to combination (added to sum of that combination)
sums.add(newSum);
previousAddedSums[j] = newSum;
if (sums.size() > k) {
sums.poll();
}
}
previous = negatives[i];
}
long[] result = new long[sums.size()];
for (int i = sums.size() - 1; i >=0 ; i--) {
result[i] = sums.poll();
}
// get sums from priority queue in proper order
return result;
// this whole method has time complexity O(n * k * log(k))
// k is less than or equal 2000 so it should be good enough ;)
}
}