如何从给定数组中随机抽取一个任意长度的非空子集?
实现思路
长度为n的数组的所有非空子集可以和1到2^n - 1的整数一一对应:整数的二进制每一位代表对应数组下标的元素是否被包含在子集中,基于这个逻辑可以不用预先生成所有子集,直接随机取数映射得到结果,性能开销极低。
- 先拿到数组的长度
n,计算非空子集总数:total = (1 << n) - 1 - 生成一个
[1, total]范围内的随机整数mask - 遍历
mask的每一个二进制位,若某一位为1,就把数组对应下标的元素加入结果子集
Java 实现代码
import java.util.ArrayList; import java.util.List; import java.util.Random; public class RandomSubset { public static void main(String[] args) { String[] s = {"a","b","c","d"}; List<String> randomSubset = getRandomNonEmptySubset(s); System.out.println(randomSubset); } private static List<String> getRandomNonEmptySubset(String[] arr) { int n = arr.length; // 非空子集总数是2^n - 1 int total = (1 << n) - 1; Random random = new Random(); // 生成[1, total]的随机整数 int mask = random.nextInt(total) + 1; List<String> subset = new ArrayList<>(); for (int i = 0; i < n; i++) { // 检查第i位是否为1 if ((mask & (1 << i)) != 0) { subset.add(arr[i]); } } return subset; } }
补充说明
如果你的数组长度超过30,需要把int类型替换为long避免溢出;如果长度超过64,可以用BitSet来实现掩码逻辑,适配更长的数组场景。
内容的提问来源于stack exchange,提问作者xiaomiao gao
相关产品推荐
相关产品推荐

