數字全排列
阿新 • • 發佈:2018-05-08
lse test 嘗試 判斷 blog 思維 main 表示 rand
數字全排列
問題描述
給一個不重復的數字數組,寫一個程序,輸出全排列。
比如給定數組:
[1, 2, 3]
輸出:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
解決思路
這個問題很經典,接下來嘗試使用數學歸納法的思想來解決這個問題。
在中學的時候,我們就知道一個長度為n的數列有n!個排列。因為第一個數字有n種情況,第二個數字有n-1種情況,第三個數字有n-2種情況……第n個數字只有一種情況了,用公式表示就是n*(n-1)*(n-2)….*1 = n!
我們換一個思維來考慮,以數組[1,2,3]為例,它的全排列為:
第一個數字為1的其他兩個數字的全排列 + 第一個數字為2的其他兩個數字的全排列 + 第一個數字為3的其他兩個數字的全排列。
那麽兩個數字的全排列怎麽算呢,以[1,2]為例,就是:
第一個數字為1的剩下的數的全排列 + 第一個數字為2的剩下的數的全排列。
- 因為剩下的只有一個數,就不用繼續了,到這就可以輸出了。
依次類推到n個數字的全排列:
- 設數組 p = {r1, r2, r3, r4, r5…., rn},設p的全排列為perm(p),設pn = p - {rn}。
- 那麽perm(p) = { r1, perm(p1) } + { r2, perm(p2) } + {r3, perm(p3) } + …… + {rn, perm(pn) }。
- 同樣思路,也可以算出perm(p1), perm(p2), perm(p3)……perm(pn)。
- 繼續,就可以使用遞歸求解了,遞歸的出口就是perm求的全排列數組裏面只有一個值。
代碼實現
下面是java的實現代碼:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3};
Test t = new Test();
t.perm(arr, 0, arr.length);
}
//求數組全排列
public void perm(int[] nums, int start, int len) {
//判斷遞歸出口,當start == len - 1時,也就是要做的全排列只有一個值 ,那麽就可以輸出了
if(start == len - 1) {
System.out.println(Arrays.toString(nums));
}else {
/*
* 沒有到遞歸出口時,這一段代碼是關鍵
* for循環模擬的是:
* { r1, perm(p1) } + { r2, perm(p2) } + {r3, perm(p3) } + …… + {rn, perm(pn) }
* 從r1, r2, r3 一直到 rn 作為第一位,求剩下的全排列
*/
for(int i = start; i < len; i++) {
swap(nums, start, i);//通過交換,依次將每個數放在第一位
perm(nums, start + 1, len);//遞歸調用
swap(nums, start, i);//交換回來,保證原數組不會變,以進行下一輪全排列
}
}
}
//交換數組中的兩個值
public void swap(int[] nums, int i, int j) {
int tem = nums[i];
nums[i] = nums[j];
nums[j] = tem;
}
}
輸出結果:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]
參考:
http://www.cnblogs.com/nokiaguy/archive/2008/05/11/1191914.html
https://blog.csdn.net/randyjiawenjie/article/details/6313729
數字全排列