leetcode60. 第k个排列/dfs+剪枝

题目: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"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

基本思想:dfs+剪枝

本题采用和全排列那道题类似的思想,但想要通过本题需要稍微修改下,一个是交换数字的位置,另一个是剪枝。

首先说一下全排列的思想:

  • 全排列相当于第一个数字加上后面数字的全排列
  • 那依次将每一个数字交换到第一个位置,对其后面的数字全排列就能得到最终的结果

本题的需要改进的第一点:

  • 这里不要将每一个数字和第一个数字交换,为了符合本题中要求的全排列的顺序,需要将该数字从原序列中删除,然后插入到第一个数字的位置。(注意:这里的第一个位置指的是函数中pos的位置)例如:1234,当以4开头的全排列首先出现的是4123,如果按照之前全排列的方法首先出现的是4231(1和4交换),这样处理是错误的!!!

本题需要改进的第二点:

  • 剪枝操作:因为我们知道要找的是第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
今日推荐