如题:如果我们想实现 数组{1,2,3,4}的排列组合,我们通常是使用递归的方式,但今天我发现另外有一个更优雅的实现方式
代码
- 先上代码
int[] nums = {1,2,3,4};
int length = nums.length;
for (int i = 1; i < (1 << length); i++) {
for (int j = 0; j < length; j++) {
if((1 << j & i) != 0){
System.out.print(nums[j] + " ");
}
}
System.out.println();
}
打印效果
1
2
1 2
3
1 3
2 3
1 2 3
4
1 4
2 4
1 2 4
3 4
1 3 4
2 3 4
1 2 3 4
解释
在案例中,利用 1、2、3、4 ……14、15的二进制中的1的位置,就相当于一个排列组合
数字 | 二进制 | 对应的元素 |
---|---|---|
1 | 0001 | 1 |
2 | 0010 | 2 |
3 | 0011 | 1,2 |
4 | 0100 | 3 |
5 | 0101 | 1,3 |
6 | 0110 | 2,3 |
7 | 0111 | 1,2,3 |
8 | 1000 | 4 |
9 | 1001 | 1,4 |
10 | 1010 | 2,4 |
11 | 1011 | 1,2,4 |
12 | 1100 | 3,4 |
13 | 1101 | 1,3,4 |
14 | 1110 | 2,3,4 |
15 | 1111 | 1,2,3,4 |
代码详细解释
for (int i = 1; i < (1 << length); i++) { // 从1到15进行遍历
for (int j = 0; j < length; j++) { // 遍历每一个数组
if((1 << j & i) != 0){ // 和i的二进制中 1 的位置相同时,才打印,否则不进行打印
System.out.print(nums[j] + " ");
}
}
System.out.println();
}
与递归相比
时间复杂度
时间复杂度都是:O(2n * n),但是递归涉及到方法的调用,效率会差很多,另外空间复杂度递归也会高很多
不足
由于数字的二进制长度有限,所以当需要排列组合的长度超过数字二进制的长度时,此方法就不适用了