【LeetCode】60. Permutation Sequence

問題描述

https://leetcode.com/problems/permutation-sequence/#/description

he set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

求n個數字組成的所有全排列字符串中的第k個字符串。

算法

因爲只要求1個,所以可以按照全排列的規則,一個個數的求出每個位置的數字,而不需要將所有的全排列字符串列出來。

對於n個字符組成的字符串{1,2,3,...,n},取第k個數時,首先可以求出第一個數,即(k-1)/(n-1個數的排列個數)

比如n=3,k=4時,全排列組合爲:

  1. 1 + {2,3}的全排列
  2. 2 + {1,3}的全排列
  3. 3 + {1,2}的全排列

我們可以首先求出目標排序的第一個數字,即(k-1)/(兩個數的排列數) = (k-1)/2 = 3/2 = 1,下標從0開始,下標1表示的數就是2

接下來,就是求出{1,3}全排列中排在第 k-2=2 個位置上的數,方法同3個字母時一樣,求出結果後爲 231

所以,可以一層一層的求出第k個順序的字符串。

時間複雜度爲O(N)

一開始是以遞歸形式寫的算法,相對容易理解,但速度慢,所以又寫了循環版本的。

代碼

循環版本

public String getPermutation(int n, int k) {
            char[] nums = new char[]{'1','2','3','4','5','6','7','8','9'};
            String tmp = "";
            for(int i=0;i<n;i++) {
                tmp += nums[i];
            }
            StringBuffer s = new StringBuffer(tmp);
            String r = "";
            while(k>0&&!s.toString().equals("")) {
                // 計算 (n-1)的排列個數cnt
                int cnt = 1, i = s.length()-1;
                while(i > 1) {
                    cnt*=i;
                    i-=1;
                }
                int pos = (k-1)/cnt;
                r += s.charAt(pos);
                s = s.deleteCharAt(pos);
                k -= pos * cnt;
            }
            return r;
        }

遞歸版本

 public String getPermutation1(int n, int k) {
            char[] nums = new char[]{'1','2','3','4','5','6','7','8','9'};
            String s = "";
            for(int i=0;i<n;i++) {
                s += nums[i];
            }
            return fun(new StringBuffer(s), k);
        }

        public String fun(StringBuffer s, int k) {
            if(k<0 || s.toString().equals("")) return "";
            int cnt = 1, tmp = s.length()-1;
            while(tmp > 1) {
                cnt*=tmp;
                tmp-=1;
            }
            int pos = (k-1)/cnt;
            return s.charAt(pos) + fun(s.deleteCharAt(pos), k - pos*cnt);
        }

LeetCode解題代碼倉庫:https://github.com/zgljl2012/leetcode-java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章