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 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 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 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("测试结束"); } }