分割红包算法
public void notSplitAdd(int [] arr, List<int[]> prepare, List<int[]> result) { if(arr[1] - arr[0] <= 1) { result.add(arr); } else { prepare.add(arr); } } public List<int[]> splitRedPack(int total, int size) { if(total <= 0 || size <= 0) throw new RuntimeException("Segmentation parameter error:" + total + " " + size); if(size > total) throw new RuntimeException("Does not support decimal division!"); List<int[]> result = new ArrayList<>(size); if(size == 1) { result.add(new int[]{0, total}); return result; } if(size == total) { for (int i = 0; i < size; i++) { result.add(new int[]{i, i+1}); } return result; } List<int[]> prepare = new ArrayList<>(size); ThreadLocalRandom r = ThreadLocalRandom.current(); for (int i = 0; i < size - 1; i++) { int n = r.nextInt(0, i == 0 ? total - 1 : prepare.size()); if(n >= prepare.size()) { notSplitAdd(new int[]{0, n + 1}, prepare, result); notSplitAdd(new int[]{n + 1, total}, prepare, result); } else { int[] arr = prepare.get(n); int n2 = r.nextInt(arr[0]+1, arr[1]); prepare.remove(n); notSplitAdd(new int[]{arr[0], n2}, prepare, result); notSplitAdd(new int[]{n2, arr[1]}, prepare, result); } } result.addAll(prepare); return result; } public void check(List<int []> list, int num) { if(list.stream().map(a->a[1] - a[0]).reduce(Integer::sum).orElse(0) != num) { throw new RuntimeException("求和错误:" + print(list)); } } public List<String> print(List<int []> list) { return list.stream() .sorted(Comparator.comparing(a->a[0])) .map(a -> a[0] + "-"+a[1]).toList(); } @Test public void test1() { System.out.println(print(splitRedPack(10000, 50))); } @Test public void test2() { for(int i = 1;i <= 10000;i++) { check(splitRedPack(10000, i), 10000); } }
分割成数组区间的形式,可以通过arr[1] - arr[0]得到想要的金额。该算法在红包分割数在20万左右性能会退化到秒级。
浙公网安备 33010602011771号