全排列、全组合 java实现

全排列

所谓全排列就是根据输入字符打印出所有字符的排列方式(分次序)。例如输入abc,所有排序的结果有,abc,cba,bac,cab,acb,bca 共6种情况。对于全排列,如果用循环的方法,需要O(n^n)的时间复杂度,其中包含大量的重复序列,需要做判断排除。显然不是一个好方法。

观察abcacbcba三者的关系,可以看出,后两者是abc的第一位abc交换所得。因此我们可以得出结论

全排列就是从第一个元素起分别与它后面的元素交换所形成的集体,用递归的方法实现,时间复杂度为O(n!)

校验:全排列的总次数为f(n)=n!

package pailie;



public class Permutation {

    int count = 0;



    public void permutation(char[] cs, int index) {

        if (index > cs.length)

            return;

        if (index == cs.length) { // 避免重复打印,也可以放进set中解决

            System.out.println(new String(cs));

            count++;

        }

        for (int i = index; i < cs.length; i++) {

            swap(cs, index, i);

            permutation(cs, index + 1);

            swap(cs, index, i); // 再次交换,保持原状

        }

    }



    private void swap(char[] cs, int index, int target) {

        char tmp = cs[index];

        cs[index] = cs[target];

        cs[target] = tmp;

    }



    public static void main(String[] args) {

        char[] cs = new char[] { 'a', 'b', 'c','d' };

        Permutation per = new Permutation();

        per.permutation(cs, 0);

        System.out.println("方法总数:" + per.count);



    }



}

全组合

从m个元素中任取n个的元素为一个组合。全组合是从m个元素中任取x(0<x<=m)个元素所有的可能性。比如abc的全组合有,a,b,c,ab,ac,bc,abc七种。

对于n个元素的集合,最终组合的结果数是2^n-1。可以这样思考,每个元素都可以用0表示不取,用1表示取该元素,每个元素都有2种可能,总的可能数有2^n,而一个都不取没有意义,所以要减1.

一位代表一个元素(字符),使用移位运算。

package pailie;



public class Combination {



    void combination(String s) {

        char[] strs = s.toCharArray();

        int n = s.length();

        int nbit = 1 << n;



        for (int i = 0; i < nbit; i++) {

            for (int j = 0; j < n; j++) {

                int tmp = 1 << j; // 由0到n右移位

                if ((tmp & i) != 0) { // 与运算,同为1时才会是1

                    System.out.print(strs[j]);

                }

            }

            System.out.println();

        }

        System.out.println("结果数为:" + (nbit - 1));

    }



    public static void main(String[] args) {

        new Combination().combination("cgz");

    }

}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值