LeetCode每日一题 2020-9-5 60.第k个排列

LeetCode每日一题 2020-9-5 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排列,最常用的方法是DFS回溯,但搜索整个解空间树的代价很大,不妨换种思路:n个数全排列,首位是1的数共 (n-1)! 个,首位是2也同样有(n-1)! 个数,也就是首位是1的序号是1~(n-1)!,首位是2的序号为(n-1)!+1 ~ 2*(n-1)! ,依次类推。确定完第一位上的数后,需要将此数删除,因为每一位上的数字不能重复。第二位上的数字用同样的方法确定,其中注意余数为零的情况,我的处理是将本位上的数序号字节置为最后一个,也就是直接符值为当前可用数的最后一个。
深知写的不好,大家可以借鉴一下思路,自己写写。

题解代码
时间0ms,超越100%,但内存使用6.3M太难看,欢迎大家评论给出优化方案!

class Solution {
public:
    string getPermutation(int n, int k) {
       int arr[10];
       arr[0]=1;
       vector<int> num;
        for(int i=1;i<=n;i++){
            num.push_back(i);
            arr[i]=arr[i-1]*i;
        }//预计算1--n的阶乘,避免重复计算
        int numIndex;//数的序号
        int tempk=k;
        string ans;
        for(int i=n-1;i>=1;i--){
            numIndex=tempk/arr[i];//先计当前算最高位数字的序号
            tempk=tempk%arr[i];//计算余数,若余数不为0,则最高位数字序号加1
            if(tempk>0){
                numIndex+=1;
            }
            if(numIndex==0){//商为0时说明应该是排满的情况,如n=3,k=6,结果应为321,所以余数为零0,取当前可用的最后一个数
                numIndex=i+1;
            }
            ans += ('0'+num[numIndex-1]);//这样比ans+=to_string(1)快
            num.erase(num.begin()+numIndex-1); 
        }
        ans+=('0'+num[0]);
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/Andy_ss/article/details/108421937