1. 程式人生 > >Leetcode演算法Java全解答--60. 第k個排列

Leetcode演算法Java全解答--60. 第k個排列

Leetcode演算法Java全解答–60. 第k個排列

文章目錄

題目

給出集合 [1,2,3,…,n],其所有元素共有 n! 種排列。

按大小順序列出所有排列情況,並一一標記,當 n = 3 時, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
給定 n 和 k,返回第 k 個排列。

說明:

給定 n 的範圍是 [1, 9]。
給定 k 的範圍是[1, n!]。

示例 1:

輸入: n = 3, k = 3
輸出: "213"
示例 2:

輸入: n = 4, k = 9
輸出: "2314"

想法

k要先變成k-1,因為現在用的是下標值,是以0開頭的,k–;

用k對(n-1)!取商,結果為資料 餘數為下一個數字

比如n=4,這樣排列出來的資料就有[1234,1243,1324,1342,1423,1432,2134,
2143,2314,2341,2413,2431,3124...]

第一輪:
可以看到以1開頭的有3*2*1 = 6種,同理2.3.4的都是這樣
這樣8/6 = 1..2(商為1,餘數為2), 結果資料就是索引為1的2(第0個是1)
然後把2從陣列中移除

第二輪
這時候資料把2除外就有[134,143,314,341,413,431]
可以看到以1開頭的有2*1 = 2種,同理3.4的都是這樣
上一把餘數是2,所以2/2 = 1..0,結果資料就是索引為1的3(第0個是1)

第三輪
這時候資料把2除外就有[14,41]
可以看到以1開頭的有1 =1種,同理4的都是這樣
上一把餘數是0,所以0/1 = 0..1,結果資料就是索引為0的1(第0個是1)

結果

超過99%的測試案例

時間複雜度/空間複雜度:n/n

總結

k–那裡沒有想到

程式碼

我的答案


public String getPermutation(int n, int k) {
    if (n <= 1) {
        return "" + n;
    }
    ArrayList arrayList = new ArrayList();
    for (int i = 1; i <= n; i++) {
        arrayList.add(i);
    }

    StringBuilder result = new StringBuilder();
    int leaf = n;
    k = k - 1;
    while (leaf > 0) {
        // 迴圈求出(n-1)階乘
        int val = 1;
        for (int i = 1; i <= leaf - 1; i++) {
            val = val * i;
        }
        // 求出下標索引index
        int index = k / val;
        result.append(arrayList.get(index));
        arrayList.remove(index);
        k = k % val;
        leaf--;
    }
    return result.toString();
}

大佬們的答案

public String better(int n, int k) {
        List<Integer> b = new ArrayList<>();
        int a[] = new int[n];
        int j = 0;

        for (int i = 0; i <= n; i++) {
            b.add(i);
        }

        for (int i = n; i > 0; i--) {
            if (k == 0) {
                for (int g = b.size() - 1; g >= 1; g--) {
                    a[n - i - 1 + g] = b.get(b.size() - g);
                }
                break;
            }
            j = pa(i - 1);
            int l = k / j + 1;
            if (k % j != 0) {
                a[n - i] = b.get(l);
                b.remove(l);
            } else {
                a[n - i] = b.get(l - 1);
                b.remove(l - 1);
            }
            k = k % j;

        }
        String s = integerFormatString(a);
        return s;
    }

    private int pa(int n) {
        int k = 1;
        if (n == 0) {
            return 1;
        }
        for (int i = 1; i <= n; i++) {
            k = k * i;
        }
        return k;
    }

    public static String integerFormatString(int[] a) {
        int len = a.length;
        char[] ch = new char[len];
        for (int i = 0; i < len; i++) {
            switch (a[i]) {
                case 0:
                    ch[i] = '0';
                    break;
                case 1:
                    ch[i] = '1';
                    break;
                case 2:
                    ch[i] = '2';
                    break;
                case 3:
                    ch[i] = '3';
                    break;
                case 4:
                    ch[i] = '4';
                    break;
                case 5:
                    ch[i] = '5';
                    break;
                case 6:
                    ch[i] = '6';
                    break;
                case 7:
                    ch[i] = '7';
                    break;
                case 8:
                    ch[i] = '8';
                    break;
                case 9:
                    ch[i] = '9';
                    break;
                default:
                    break;
            }
        }
        String str = new String(ch);
        return str;
    }

測試用例

@Test
public void test060() {
    // 建立測試案例
    int n1 = 3;
    int k1 = 3;
    int n2 = 3;
    int k2 = 6;

    // 測試案例期望值
    String expResult1 = "213";
    String expResult2 = "321";


    // 執行方法
    Solution060 solution060 = new Solution060();
    String result1 = solution060.getPermutation(n1,k1);
    String result2 = solution060.getPermutation(n2,k2);

    // 判斷期望值與實際值
    Assert.assertEquals(expResult1, result1);
    Assert.assertEquals(expResult2, result2);

}

其他

程式碼託管碼雲地址:https://gitee.com/lizhaoandroid/LeetCodeAll.git

檢視其他內容可以點選專欄或者我的部落格哈:https://blog.csdn.net/cmqwan

“大佬們的答案” 標籤來自leetcode,侵權請聯絡我進行刪改

如有疑問請聯絡,聯絡方式:QQ3060507060