1. 程式人生 > >數字全排列

數字全排列

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

數字全排列