排列組合算法


排列和組合是組合學最基本的概念。

組合,則是指從給定的若干個元素中取出指定個數的元素,不考慮順序。

排列,就是指從給定的若干個元素中取出指定個數的元素,並且要考慮順序。

總之,排列與元素的順序有關,組合與元素的順序無關。例如:abc和bca是同一個組合,但卻是兩個排列。

組合

1.最容易想到的,一個集合里取n個元素進行組合。

代碼如下:

import java.util.Arrays;
/**
 * 模擬進制:一個集合里取n個元素進行組合
 * @author Jeby
 *
 */
public class CombineOfn {
	public static void main(String[] args) {
		String[] s = {"a", "b", "c", "d", "e"};
		combine(s,3);
	}
	
	public static void combine(String[] s, int n) {
	    int[] dig = new int[s.length];                //進位用數組
	    StringBuilder state = new StringBuilder();
	    for (int i=s.length-1, j=0; i>=0; i--, j++) { //初始化進位數組狀態
	        if (s.length-i>n) {                       //如s有5個元素,n為2,即取2個元素組合
	            dig[i] = 0;                           //那么初始狀態為 00011
	        }
	        else {
	            dig[i] = 1;
	        }
	        state.append(dig[i]);
	    }
	    String max = state.toString();                //獲取進位的最大狀態,如上面的假設 11000
	    String min = state.reverse().toString();      //獲取進位的最小狀態,即數組初始狀態 00011
	    while (max.compareTo(min) >= 0) {             //當最小狀態比不大於最大狀態的時候循環
	        if (min.length()-min.replaceAll("1", "").length() == n) {       //當進位狀態中
	            for (int i=0; i<s.length; i++) {                            //1的個數為n時打印
	                if (dig[i] == 1) {System.out.printf("%s ", s[i]);}
	            }
	            System.out.println();
	        }
	        dig[dig.length-1]++;                               //模擬進位,末位+1
	        for (int i=dig.length-1; i>0; i--) {
	            if (dig[i] == 2) {                             //當某位進位位置達到最大狀態時
	                dig[i] = 0;                                //清0
	                dig[i-1]++;                                //往前進位
	            } else {
	                break;                                     //不滿足進位 break
	            }
	        }
	        min = Arrays.toString(dig).replaceAll("\\D+", ""); //重新獲得進位狀態
	    }
	}
}

2.迭代一個集合的全部組合。

例如,[a,b,c]的全部組合為[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]

代碼如下:

import java.util.ArrayList;
import java.util.List;
/**
 * 迭代全部組合
 * 
 * 【效果】
 * 	原序列:
 *	[a, b, c]
 *	全部組合序列:
 *	[[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]]
 * @author Jeby
 *
 */
public class Combinations {
    /** 
	 * 取組合方法
     * 參數: list原始數組
     * 返回:  包含所有組合數組的數組
     */
    public static List<List<Object>> getCombinations(List<Object> list) {
        List<List<Object>> result = new ArrayList<List<Object>>();
        List<Object> combine = null;
        long n = (long)Math.pow(2,list.size());
        for (long li=0L; li<n; li++) {
            combine = new ArrayList<Object>();
            for (int i=0; i<list.size(); i++) {
                if ((li>>>i&1) == 1)
                    combine.add(list.get(i));
            }
            result.add(combine);
        }
        return result;
    }
    /**
	* 測試
	*/
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        list.add("a");
        list.add("b");
        list.add("c");
        List<List<Object>> result = getCombinations(list);
        System.out.println("原序列:");
        System.out.println(list.toString());
        System.out.println("全部組合序列:");
        System.out.println(result.toString());
    }

}

3.多個集合中分別取出一個元素進行組合。

代碼如下:

/**
 * 模擬進制:多個集合中分別取出一個元素進行組合
 * @author Jeby
 *
 */
public class CombinateByte {
	public static void main(String[] args) {
		String[][] s = {{"a","b"}, {"c", "d", "e"}, {"f", "g"}};
		combie(s);
	}
	
	private static void combie(String[][] s) {
	    int[] dig = new int[s.length];                   //用來模擬進位
	    while (dig[0] < s[0].length) {                   //進位最高位不滿最大的時候循環
	        for (int i=0; i<s.length; i++) {
	            System.out.print(s[i][dig[i]]);          //打印每個數組的當前進位位置的元素
	        }
	        System.out.println();                        //換行
	        dig[dig.length-1]++;                         //模擬進位,末位+1
	        for (int i=dig.length-1; i>0; i--) {
	            if (dig[i] == s[i].length) {             //當某進位位置達到最大時往前進位
	                dig[i] = 0;                          //當前位清0恢復最小狀態
	                dig[i-1]++;                          //進位
	            } else {
	                break;                               //不滿足進位時break
	            }
	        }
	    }
	}

}

排列

1.獲得集合全排列的一個實現算法。

代碼如下:

import java.util.Arrays;

/**
 * 獲得數組全排列的一個實現算法
 *
 */
public class TestAllP {
	static String[] array = { "x", "y", "z" };

	public static void main(String[] args) {
		getAllOrder(array,0,array.length - 1);
	}

	public static void getAllOrder(Object[] arr,int begin, int end) {
		if (begin == end) {
			check();
		} else {
			for (int i = begin; i <= end; i++) {
				swap(arr,begin, i);
				getAllOrder(arr,begin + 1, end);
				swap(arr,i, begin);
			}
		}
	}

	/**
	 * 這里應該加上各種防止無效交換的情況,比如位置相同,或者2個位置的數據相同
	 */
	public static void swap(Object[] arr,int from, int to) {
		if (from == to) {
			return;
		}
		Object tmp = arr[from];
		arr[from] = arr[to];
		arr[to] = tmp;
	}

	/**
	 * 排列拿到了,可以進行進一步的篩選了。
	 */
	public static void check() {
		System.out.println(Arrays.toString(array));
	}
}

2.獲得一個集合中若干個元素的排列,可以結合從一個集合里取n個元素進行組合然后再對每一組組合數據進行全排列,在此不再累述。

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合算法 排列組合公式及排列組合算法
 
粤ICP备14056181号  © 2014-2021 ITdaan.com