You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
2.8 KiB

2 years ago
package class_2022_04_1_week;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
// 给定一个数组arr含有n个数字都是非负数
// 给定一个正数k
// 返回所有子序列中累加和最小的前k个子序列累加和
// 假设K不大怎么算最快
public class Code06_TopMinSubsquenceSum {
public static int[] topMinSum1(int[] arr, int k) {
ArrayList<Integer> allAns = new ArrayList<>();
process(arr, 0, 0, allAns);
allAns.sort((a, b) -> a.compareTo(b));
int[] ans = new int[k];
for (int i = 0; i < k; i++) {
ans[i] = allAns.get(i);
}
return ans;
}
public static void process(int[] arr, int index, int sum, ArrayList<Integer> ans) {
if (index == arr.length) {
ans.add(sum);
} else {
process(arr, index + 1, sum, ans);
process(arr, index + 1, sum + arr[index], ans);
}
}
public static int[] topMinSum2(int[] arr, int k) {
Arrays.sort(arr);
// (最右的下标,集合的累加和)
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[1] - b[1]);
heap.add(new int[] { 0, arr[0] });
int[] ans = new int[k];
// ans[0] = 0
// 0 1 2 k-1
// k个
for (int i = 1; i < k; i++) {
int[] cur = heap.poll();
// (7, 100)
// 左 8, 100 - arr[7] + arr[8]
// 右 8 100 + arr[8]
int last = cur[0];
int sum = cur[1];
ans[i] = sum;
if (last + 1 < arr.length) {
heap.add(new int[] { last + 1, sum - arr[last] + arr[last + 1] });
heap.add(new int[] { last + 1, sum + arr[last + 1] });
}
}
return ans;
}
// 为了测试
public static int[] randomArray(int len, int value) {
int[] arr = new int[len];
for (int i = 0; i < len; i++) {
arr[i] = (int) (Math.random() * value);
}
return arr;
}
// 为了测试
public static boolean equals(int[] ans1, int[] ans2) {
if (ans1.length != ans2.length) {
return false;
}
for (int i = 0; i < ans1.length; i++) {
if (ans1[i] != ans2[i]) {
return false;
}
}
return true;
}
// 为了测试
public static void main(String[] args) {
int n = 10;
int v = 40;
int testTime = 5000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * n) + 1;
int[] arr = randomArray(len, v);
int k = (int) (Math.random() * ((1 << len) - 1)) + 1;
int[] ans1 = topMinSum1(arr, k);
int[] ans2 = topMinSum2(arr, k);
if (!equals(ans1, ans2)) {
System.out.println("出错了!");
System.out.print("arr : ");
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
System.out.println("k : " + k);
for (int num : ans1) {
System.out.print(num + " ");
}
System.out.println();
for (int num : ans2) {
System.out.print(num + " ");
}
System.out.println();
break;
}
}
System.out.println("测试结束");
}
}