排列组合算法

来源:互联网 发布:macbook air如何写编程 编辑:程序博客网 时间:2024/06/01 18:51

排列和组合是组合学最基本的概念。

组合,则是指从给定的若干个元素中取出指定个数的元素,不考虑顺序。

排列,就是指从给定的若干个元素中取出指定个数的元素,并且要考虑顺序。

总之,排列与元素的顺序有关,组合与元素的顺序无关。例如:abc和bca是同一个组合,但却是两个排列。

组合

1.最容易想到的,一个集合里取n个元素进行组合。

代码如下:

[java] view plaincopy
  1. import java.util.Arrays;  
  2. /** 
  3.  * 模拟进制:一个集合里取n个元素进行组合 
  4.  * @author Jeby 
  5.  * 
  6.  */  
  7. public class CombineOfn {  
  8.     public static void main(String[] args) {  
  9.         String[] s = {"a""b""c""d""e"};  
  10.         combine(s,3);  
  11.     }  
  12.       
  13.     public static void combine(String[] s, int n) {  
  14.         int[] dig = new int[s.length];                //进位用数组  
  15.         StringBuilder state = new StringBuilder();  
  16.         for (int i=s.length-1, j=0; i>=0; i--, j++) { //初始化进位数组状态  
  17.             if (s.length-i>n) {                       //如s有5个元素,n为2,即取2个元素组合  
  18.                 dig[i] = 0;                           //那么初始状态为 00011  
  19.             }  
  20.             else {  
  21.                 dig[i] = 1;  
  22.             }  
  23.             state.append(dig[i]);  
  24.         }  
  25.         String max = state.toString();                //获取进位的最大状态,如上面的假设 11000  
  26.         String min = state.reverse().toString();      //获取进位的最小状态,即数组初始状态 00011  
  27.         while (max.compareTo(min) >= 0) {             //当最小状态比不大于最大状态的时候循环  
  28.             if (min.length()-min.replaceAll("1""").length() == n) {       //当进位状态中  
  29.                 for (int i=0; i<s.length; i++) {                            //1的个数为n时打印  
  30.                     if (dig[i] == 1) {System.out.printf("%s ", s[i]);}  
  31.                 }  
  32.                 System.out.println();  
  33.             }  
  34.             dig[dig.length-1]++;                               //模拟进位,末位+1  
  35.             for (int i=dig.length-1; i>0; i--) {  
  36.                 if (dig[i] == 2) {                             //当某位进位位置达到最大状态时  
  37.                     dig[i] = 0;                                //清0  
  38.                     dig[i-1]++;                                //往前进位  
  39.                 } else {  
  40.                     break;                                     //不满足进位 break  
  41.                 }  
  42.             }  
  43.             min = Arrays.toString(dig).replaceAll("\\D+"""); //重新获得进位状态  
  44.         }  
  45.     }  
  46. }  

2.迭代一个集合的全部组合。

例如,[a,b,c]的全部组合为[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]

代码如下:

[java] view plaincopy
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. /** 
  4.  * 迭代全部组合 
  5.  *  
  6.  * 【效果】 
  7.  *  原序列: 
  8.  *  [a, b, c] 
  9.  *  全部组合序列: 
  10.  *  [[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]] 
  11.  * @author Jeby 
  12.  * 
  13.  */  
  14. public class Combinations {  
  15.     /**  
  16.      * 取组合方法 
  17.      * 参数: list原始数组 
  18.      * 返回:  包含所有组合数组的数组 
  19.      */  
  20.     public static List<List<Object>> getCombinations(List<Object> list) {  
  21.         List<List<Object>> result = new ArrayList<List<Object>>();  
  22.         List<Object> combine = null;  
  23.         long n = (long)Math.pow(2,list.size());  
  24.         for (long li=0L; li<n; li++) {  
  25.             combine = new ArrayList<Object>();  
  26.             for (int i=0; i<list.size(); i++) {  
  27.                 if ((li>>>i&1) == 1)  
  28.                     combine.add(list.get(i));  
  29.             }  
  30.             result.add(combine);  
  31.         }  
  32.         return result;  
  33.     }  
  34.     /** 
  35.     * 测试 
  36.     */  
  37.     public static void main(String[] args) {  
  38.         ArrayList<Object> list = new ArrayList<Object>();  
  39.         list.add("a");  
  40.         list.add("b");  
  41.         list.add("c");  
  42.         List<List<Object>> result = getCombinations(list);  
  43.         System.out.println("原序列:");  
  44.         System.out.println(list.toString());  
  45.         System.out.println("全部组合序列:");  
  46.         System.out.println(result.toString());  
  47.     }  
  48.   
  49. }  

3.多个集合中分别取出一个元素进行组合。

代码如下:

[java] view plaincopy
  1. /** 
  2.  * 模拟进制:多个集合中分别取出一个元素进行组合 
  3.  * @author Jeby 
  4.  * 
  5.  */  
  6. public class CombinateByte {  
  7.     public static void main(String[] args) {  
  8.         String[][] s = {{"a","b"}, {"c""d""e"}, {"f""g"}};  
  9.         combie(s);  
  10.     }  
  11.       
  12.     private static void combie(String[][] s) {  
  13.         int[] dig = new int[s.length];                   //用来模拟进位  
  14.         while (dig[0] < s[0].length) {                   //进位最高位不满最大的时候循环  
  15.             for (int i=0; i<s.length; i++) {  
  16.                 System.out.print(s[i][dig[i]]);          //打印每个数组的当前进位位置的元素  
  17.             }  
  18.             System.out.println();                        //换行  
  19.             dig[dig.length-1]++;                         //模拟进位,末位+1  
  20.             for (int i=dig.length-1; i>0; i--) {  
  21.                 if (dig[i] == s[i].length) {             //当某进位位置达到最大时往前进位  
  22.                     dig[i] = 0;                          //当前位清0恢复最小状态  
  23.                     dig[i-1]++;                          //进位  
  24.                 } else {  
  25.                     break;                               //不满足进位时break  
  26.                 }  
  27.             }  
  28.         }  
  29.     }  
  30.   
  31. }  

排列

1.获得集合全排列的一个实现算法。

代码如下:

[java] view plaincopy
  1. import java.util.Arrays;  
  2.   
  3. /** 
  4.  * 获得数组全排列的一个实现算法 
  5.  * 
  6.  */  
  7. public class TestAllP {  
  8.     static String[] array = { "x""y""z" };  
  9.   
  10.     public static void main(String[] args) {  
  11.         getAllOrder(array,0,array.length - 1);  
  12.     }  
  13.   
  14.     public static void getAllOrder(Object[] arr,int begin, int end) {  
  15.         if (begin == end) {  
  16.             check();  
  17.         } else {  
  18.             for (int i = begin; i <= end; i++) {  
  19.                 swap(arr,begin, i);  
  20.                 getAllOrder(arr,begin + 1, end);  
  21.                 swap(arr,i, begin);  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     /** 
  27.      * 这里应该加上各种防止无效交换的情况,比如位置相同,或者2个位置的数据相同 
  28.      */  
  29.     public static void swap(Object[] arr,int from, int to) {  
  30.         if (from == to) {  
  31.             return;  
  32.         }  
  33.         Object tmp = arr[from];  
  34.         arr[from] = arr[to];  
  35.         arr[to] = tmp;  
  36.     }  
  37.   
  38.     /** 
  39.      * 排列拿到了,可以进行进一步的筛选了。 
  40.      */  
  41.     public static void check() {  
  42.         System.out.println(Arrays.toString(array));  
  43.     }  
  44. }  

2.获得一个集合中若干个元素的排列,可以结合从一个集合里取n个元素进行组合然后再对每一组组合数据进行全排列,在此不再累述。

0 0
原创粉丝点击