[土味]Java遍历无序全排列组合

Java遍历无序全排列组合

在做迷宫生成,拆墙时需要用到无序的全排列,网上找到一段代码,也没有注释,看不懂,自己研究了下,把分析过程贴出来.

原文链接
java排列组合 实现全排列,支持有序和无序

先上代码

/**
     * 方法一:无序
     *
     * @param data
     * @param <E>
     * @return
     */
    public static <E> List<List<E>> arrangeSelect1(List<E> data) {

        int size = data.size();
        // 一共 2^size-1 个无序全排列组合
        int count = (int) (Math.pow(2, size) - 1);

        List<List<E>> arrangeAllSet = new ArrayList<>();

        for (int i = 1; i <= count; i++) {

            List<E> arrangeSet = new ArrayList<>();

            for (int j = 0; j < size; j++) {
                if ((i << (31 - j)) >> 31 == -1) {
                    arrangeSet.add(data.get(j));
                }
            }
            arrangeAllSet.add(arrangeSet);
        }
        return arrangeAllSet;
    }

	@Test
    public void test() {
        List<Integer> data = new ArrayList<Integer>();
        for(int i=0; i<3; i++) {
            data.add(i);
        }

        List<List<Integer>> arrangeList1 = arrangeSelect1(data);
        System.out.println(arrangeList1);

    }

他这边主要用到了左移和右移,特点如下
<< 左移,丢弃最高位(符号位同样丢弃),0补最低位
>> 右移 符号位不变,左边补上符号位

下面上分析过程
int a = 1;
0x00000001 (1的16进制)
0000 0000 0000 0000 0000 0000 0000 0001 (1的二进制)

执行 1 << 31
1000 0000 0000 0000 0000 0000 0000 0000

执行 1 << 31 >> 1
1100 0000 0000 0000 0000 0000 0000 0000

执行 1 << 31 >> 2
1110 0000 0000 0000 0000 0000 0000 0000

执行 1 << 31 >> 31 = -1
1111 1111 1111 1111 1111 1111 1111 1111

执行 1 << 10
0000 0000 0000 0000 0000 0100 0000 0000

执行 1 << 10 >> 31 = 0
0000 0000 0000 0000 0000 0000 0000 0000

结论: 对于1来说,只有一种情况可以让表达式 1 << (31 - j)) >> 31 == -1 成立,就是 j=0
对于2,3,4,5…来说,也可以用同样的方法得到 j 的取值,结果如下:

i 表达式j 取值
1 << 31 >> 31 = -1j=0
2 << 30 >> 31 = -1j=1
3 << 31 >> 31 = -1j=0
3 << 30 >> 31 = -1j=1
4 << 29 >> 31 = -1j=2
5 << 31 >> 31 = -1j=0
5 << 29 >> 31 = -1j=2
6 << 30 >> 31 = -1j=1
6 << 29 >> 31 = -1j=2
7 << 31 >> 31 = -1j=0
7 << 30 >> 31 = -1j=1
7 << 29 >> 31 = -1j=2
8 << 28 >> 31 = -1j=3
  • 横向看,可以看到数字3对应的 j 有两种情况,7有3种,其实可以看成3 = 1 + 2, 3的表达式是有1和2的表达式组合起来的,同样7 = 1 + 2 + 4,所以7的表达式就是1,2,4的表达式组合起来的.

  • 纵向看 j取值列,可以发现,
    第一行是1个元素{0}的全排列{0},
    第1-4行是两个元素{0, 1}的全排列{[0],[1],[0,1]},
    第1-12行是3个元素{0, 1, 2}的全排列{[0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2]}

  • 所以通过 i 和 j 的两重循环,就可以将所有的无序排列组合全部打印出来.

  • 至于具体的原理分析,可以看我的文章 自制迷宫代码中的 arrangeSelect1() 方法,里面有具体分析。

参考资料
java排列组合 实现全排列,支持有序和无序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值