leetcode60。k番目の順列/ dfs + pruning

トピック:60. k番目の順列

セット[1,2,3、...、n]を指定すると、そのすべての要素はn!個の順列を持ちます。

すべての順列をサイズ順にリストし、1つずつマークします。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"

ソース:LeetCode(LeetCode)
リンク:https ://leetcode-cn.com/problems/permutation-sequence
著作権はLeetCode が所有しています商用転載については、正式な許可書にご連絡ください。非商用転載については、出典を明記してください。

基本的な考え方:dfs + pruning

この質問は、完全な配置と同様の考え方を使用していますが、この質問に合格する場合は少し変更する必要があります。1つは番号の位置を交換することで、もう1つはプルーニングすることです。

最初に完全配列のアイデアについて話しましょう:

  • 完全な配置は、最初の番号と次の番号の完全な配置に相当します
  • 次に、各番号を最初の位置に順番に入れ替え、その後ろにあるすべての番号を配置して、最終的な結果を取得します

改善が必要なこの質問の最初のポイント:

  • ここで各番号を最初の番号と交換しないでください。この質問で必要な完全な配置の順序に準拠するには、番号を元のシーケンスから削除してから、最初の番号の位置に挿入する必要があります。(注:ここでの最初の位置とは、関数内のposの位置を指します)例:1234、4で始まる完全な配置が最初に表示されるときは4123ですが、前の完全な配置方法によると、最初に表示されるのは4231(1および4交換)、この扱いは間違っています!

この質問を改善する必要がある2番目の点:

  • 剪定操作:k番目の順列を探していることがわかっているので、この数で始まる順列の数を使用して剪定を実行できます。
    例:1234、9番目の順列を見つける必要があります。最初に1で始まる6(つまり、234の完全順列)、6 <9であるため、9番目の順列は1で始まってはならず、次の全体を見つける必要があります。 3番目の順列。
    次に、2から始まる完全な順列を探します。6、6> 3がまだある場合、9番目の順列は2から始まります。同様に、次の各桁を順番に決定します。
class Solution {
    
    
public:
    
    string cur = "";
    int qn;
    string getPermutation(int n, int k) {
    
    
        string nums = "";
        for(int i = 0; i < n; ++i){
    
    
            nums += ((i + 1) + '0');
        }
        qn = n;
        int cnt = k;
        dfs(nums, 0, cnt);
        
        return cur;
    }
    bool dfs(string nums, int pos, int &cnt){
    
    
        if(cnt == 1){
    
    
            cur = nums;
            return true;
        }

        bool flag = false;
        //第一个数字加上其后面数字的全排列
        //依次将每一个数字放在第一位,对其后面的数字进行全排列
        
        for(int i = pos; i < qn && !flag; ++i){
    
    
            //剪枝
            //计算以该数字开头的全排列的个数
            int sum_pos = fun(qn - pos - 1);
            if(sum_pos < cnt){
    
    
                cnt -= sum_pos;
                continue;
            }

            //将当前字符从字符串中删除,插入到pos指示的位置
            string cur = nums;              
            char t = nums[i];
            cur.erase(cur.begin() + i);
            cur.insert(cur.begin() + pos, t);

            flag = dfs(cur, pos + 1, cnt);
        }
        return flag;
    }
    int fun(int num){
    
    
        int res = 1;
        while(num){
    
    
            res *= num;
            num--; 
        }
        return res;
    }
};

おすすめ

転載: blog.csdn.net/qq_31672701/article/details/108424433