字符串的全排列和全组合

输入:abc

输出:bac,cba,acb,bca,cab,abc

全排列的问题:

基本思想就是递归,固定第一个数,先求后面的所有的数的全排列,再用这个固定的数和后面的每个数来交换,注意重复字符的处理。

public ArrayList<String> Permutation(String str) {
        ArrayList<String> list = new ArrayList<String>();
        if(str!=null && str.length()>0){
             helper(str.toCharArray(),list,0);
             Collections.sort(list);
        }
        return list;
    }
    public void helper(char[] chars,ArrayList<String> list,int i) {
        if(i==chars.length-1) {
            list.add(String.valueOf(chars));
            return;
        }
        else
        {
Set<Character> charSet = new HashSet<Character>();
for(int j=i;j<chars.length;j++) { if(i==j||!charSet.contains(chars[j])) {//这里唯一比较难理解的就是i==j,这里就是为了做一次无用功,先让后面的做全排列,以及对重复字符的处理。 charSet.add(chars[j]);
swap(chars,i,j); helper(chars,list,i
+1); swap(chars,j,i); } } } } private void swap(char[] cs,int i,int j){ char temp = cs[i]; cs[i] = cs[j]; cs[j] = temp; }

利用全排列解决一些问题:

比如从1,2,3,4里面拿出3个数,组成不重复的

就是在退出的地方重新建一个数组,但只拿它的前n-1位

 

全组合:

public ArrayList<String> Comb(String str) {
        char[] chars = str.toCharArray();
        ArrayList<String> list = new ArrayList<String>();
        int combNum=1<<str.length();
        for(int i=1;i<combNum;i++) {
            StringBuffer temp=new StringBuffer(); 
            for(int j=0;j<str.length();j++) {
                int k=1<<j;
                if((k&i)!=0) {
                    temp.append(chars[j]);
                }
                
            }
            if(!list.contains(temp.toString()))
               list.add(temp.toString());
        }
        return list;
    }

打靶问题:

public int[] label= {0,1,2,3,4,5,6,7,8,9,10};
    public void Compute(int score,int num,ArrayList<Integer> list){
        if(score<0||score>(num+1)*10) return;
        if(num==0) {
            System.out.println(list);
        }
        for(int i=0;i<11;i++) {
            list.add(label[i]);
            Compute(score-label[i],num-1,list);
            list.remove(list.size()-1);            
        }
    }

 m个水果放到n个盘子里,问有多少种情况。重复的不算,和全组合是有点像的(5,1,1和1,1,5是同一种分法)

//m个水果放到n个盘子里面
    public int fun(int m,int n) {
        if(m==0||n==1) return 1;
        if(n>m) return fun(m,m);
        else
            return fun(m,n-1)+fun(m-n,n);//第一个是有一个盘子不放水果,第二个是,每个盘子都放水果(先每个盘子都放一个,再去放其他的)
    }
    public int fun(int m,int n) {
        if(m==0||n==1) return 1;
        int[][] dp=new int[m+1][n+1];
        for(int i=0;i<=n;i++) dp[0][i]=1;
        for(int j=0;j<=m;j++) dp[j][1]=1;
        for(int i=1;i<=m;i++) {
            for(int j=1;j<=n;j++) {
                if(j<=i)
                    dp[i][j]=dp[i][j-1]+dp[i-j][j];//和上面原理一样的,第一个是有一个盘子不放东西,第二个是所有盘子都放东西
                else
                    dp[i][j]=dp[i][i];                    
            }
        }
        return dp[m][n];
    }

 

posted @ 2019-03-19 19:49  LeeJuly  阅读(211)  评论(0)    收藏  举报