全排和组合

全排和组合

使用递归

import java.util.ArrayList;

/**
 * @Author: TJW
 * @Description:
 * @Date: 2018/12/5
 */
public class Ank_recursion {



    public static void main(String[] args){
        ArrayList<Integer[]> result = new ArrayList<>();
        int list[]=new int[]{1,2,3};
        perm(list,0,2,result);
        for(int i=0;i<result.size();i++){
            print(result.get(i));
        }
    }


    //主要思路:分成0-s和s-e
    public static void perm(int list[], int s, int e, ArrayList<Integer[]> result){
        if(s>e){
            result.add(copy(list));
        }else{
            for(int i=s;i<=e;i++){
                swap(list,s,i);
                perm(list,s+1,e,result);
                swap(list,s,i);
            }

        }
    }
    /**
     perm(list=[1,2,3],s=0;e=2;result[])
     list=[1,2,3]
     perm(list=[1,2,3],s=1;e=2;result[])    <-----  \
     list=[1,2,3]                                   \
     perm(list=[1,2,3],s=2;e=2;result[])  <-----\   \
     list=[1,2,3]                               \   \
     perm(list=[1,2,3],s=3;e=2;result[])        \   \
     result=[{1,2,3}];                          \   \
     list=[1,2,3]-------------------------------\   \
     liat=[1,2,3]-----------------------------------\
     list=[1,3,2]
     perm(list=[1,3,2],s=3;e=2;result[])
    */


    public static void swap(int[] a, int x, int y){
        int temp = a[x];
        a[x] = a[y];
        a[y] = temp;
    }

    public static Integer[] copy(int[] a){
        Integer[] result = new Integer[a.length];
        for(int i=0;i<a.length;i++){
            result[i] = a[i];
        }
        return  result;
    }

    public static void print(Integer[] a){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]);
        }
        System.out.println();
    }
}

import java.util.ArrayList;

/**
 * @Author: TJW
 * @Description:
 * @Date: 2018/12/6
 */
public class Cnk_recursion {

    public static void main(String[] args) {
        ArrayList<Integer[]> result = new ArrayList<>();
        int list[]=new int[]{1,2,3,4};
        int subset[]=new int[2];
        combine(list,4,2,subset,result);
        for(int i=0;i<result.size();i++){
            print(result.get(i));
        }

    }

    public static void combine(int s[],int n, int k, int subset[],ArrayList<Integer[]> result){
        if(k==0){
            result.add(copy(subset));
        }else{
            for(int i=n;i>=k;i--){
                subset[k-1] = s[i-1];
                combine(s,i-1,k-1,subset,result);
            }
        }
    }

    public static Integer[] copy(int[] a){
        Integer[] result = new Integer[a.length];
        for(int i=0;i<a.length;i++){
            result[i] = a[i];
        }
        return  result;
    }

    public static void print(Integer[] a){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]);
        }
        System.out.println();
    }
}

非递归实现方法

import org.omg.Messaging.SYNC_WITH_TRANSPORT;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author: TJW
 * @Description:
 * @Date: 2018/12/6
 */
public class Ank {

    public static void main(String[] args) {
        Integer[] list = new Integer[]{1,2,3,4};
        do {
            for(int i=0;i<list.length;i++){
                System.out.print(list[i]);
            }
            System.out.println();
        }while (next_permutation(list));
    }

    /*
    https://www.cnblogs.com/autosar/archive/2012/04/08/2437799.html
    算法是:
    (1) 从右向左,找出第一个比右边数字小的数字A。
    (2) 从右向左,找出第一个比A大的数字B。
    (3) 交换A和B。
    (4) 将A后面的串(不包括A)反转。
    */
    public static boolean next_permutation(Integer[] list){
        int temp = list[list.length-1];
        int indexA=-1,indexB=-1;
        //第一个比temp小的为A
        for(int i=list.length-1;i>=0;i--){
            if(list[i]<temp){
                indexA = i;
                break;
            }else{
                temp = list[i];
            }
        }
        if(indexA==-1){
            return false;
        }
        //第一个比A大的为B
        for(int i=list.length-1;i>=0;i--){
            if(list[i]>list[indexA]){
                indexB = i;
                break;
            }
        }
        if(indexB==-1){
            return false;
        }
        //A<=>B
        int tempAB = list[indexA];
        list[indexA] = list[indexB];
        list[indexB] = tempAB;

        //A以后的翻转
        for(int i=indexA+1;i<list.length-1;i++){
            int tmp = list[i];
            list[i] = list[i+1];
            list[i+1] = tmp;
        }

        return true;
    }
}
/**
 * @Author: TJW
 * @Description:
 * @Date: 2018/12/6
 */
public class Cnk {

    public static void main(String[] args) {
        int[] list= new int[]{1,2,3,4};
        combination(list,4,2);
    }


    /*
    https://www.cnblogs.com/autosar/archive/2012/04/08/2437799.html
    (1) 从左到右扫描0/1列表,如果遇到“10”组合,就将它转换为”01”.
    (2) 将上一步找出的“10”组合前面的所有1全部移到set的最左侧。
    (3) 重复(1) (2)直到没有“10”组合出现。
    */
    public static void combination(int[] list, int n, int k){
        int[] vec = new int[list.length];
        for(int i=0;i<k;i++){
            vec[i]=1;
        }
        for(int i=k;i<n;i++){
            vec[i]=0;
        }

        boolean has_next = true;
        while(has_next){
            //print
            for(int i=0;i<list.length;i++){
                if(vec[i]==1){
                    System.out.print(list[i]);
                }
            }
            System.out.println();
            //calculate
            has_next=false;
            for(int i=0;i<list.length-1;i++){
                if(vec[i]==1&&vec[i+1]==0){
                    vec[i]=0;
                    vec[i+1]=1;
                    int count = 0;
                    for(int j=0;j<i;j++){
                        if(vec[j]==1){
                            count++;
                        }
                    }
                    if(count<i){
                        for(int j=0;j<count;j++){
                            vec[j]=1;
                        }
                        for(int j=count;j<i;j++){
                            vec[j]=0;
                        }
                    }
                    has_next=true;
                    break;
                }
            }

        }

    }
}

参考(一个使用C++的实现):https://www.cnblogs.com/autosar/archive/2012/04/08/2437799.html

猜你喜欢

转载自blog.csdn.net/xiaowei_innocence/article/details/84867191
今日推荐