[leetcode] 60.Permutation Sequence

题目:
The 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):

“123”
“132”
“213”
“231”
“312”
“321”
Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.
题意:集合[1,2,3…n]共有n!种不同的排列。
把这些排列按照字符串顺序排列,找出第k个排列。比如对于n=3时有以上六种排列,第五个排列就是312.

思路:解决该题目最蛮力的方法是找出所有的排列,然后排序后找出第k个,时间复杂度将会达到O(n!+nlgn),太低效!

观察全排列的规律我们可以发现,如果是有n个数字,那么第一位上可以有n个不同的选择,第二位到第n位一共有(n-1)!种情况,也就是说第一位的每一个数字确定后,后面的n-1位会有(n-1)!种不同的可能。比如上面的例子中,当第一位是1时,后两位有两种可能,当然第一位是2或者3时也是如此。

那么我们就可以用来确定第m位的数值。我们从第一位往后依次确定各位的数值,所以确定第m位时代表前m-1位已经确定。由于第m+1到第n一共有n-m个位置,共有可能性(n-m)!,所以说第m位每个数值对应有(n-m)!个可能值。那么第m位上的数值应该是第 index = k/(n-m)! + ((k%(n-m)! != 0)?1:0)位数;使用一个char数组代表哪些数字已经使用过了,使用过了则改为’ ‘,否则应该是’0’,’1’..’9’之类,所以只需要依次遍历该数组就可以找到第index位数值。很明显是一个递归过程,依次确定每一位上应该是哪个数字。

以上。
代码如下:

class Solution {
public:
    string getPermutation(int n, int k) {
        if(n == 1 && k == 1)return "1";
        else if(n < 1 || k < 1)return "";
        int factorial = 1;
        vector<char> ints;
        for(int i = 1; i <= n; i++){
            ints.push_back(i + '0');
            factorial *= i;
        }
        if(k > factorial)return "";
        string result;
        return getKthString(factorial/n,ints,k,result,n);//factorial/n即(n-1)!
    }
    string getKthString(int subFactorial, vector<char>& ints,int k, string& result,int kinds_this_index){
        if(kinds_this_index == 1){
            for(int i = 0; i < ints.size(); ++i)
                if(ints[i] != ' '){
                    result.push_back(ints[i]);
                    break;
                }
            return result;
        }
        if(k == 1){//如果是确定第m位时需要找的是第一个位置,那么只需要遍历ints数组,依次存入到结果中即可。
            for(int i = 0; i < ints.size(); ++i)
                if(ints[i] != ' '){
                    result.push_back(ints[i]);
                }
            return result;
        }
        int index = k/subFactorial + ((k%subFactorial != 0)?1:0);//找出第m位上需要存放的是按照顺序的第几个数值。
        int count = 0;
        for(int i = 0; i < ints.size(); i++){
            if(ints[i] != ' ')count++;
            if(count == index){
                result.push_back(ints[i]);
                ints[i] = ' ';
                break;
            }
        }
        --kinds_this_index;
        return getKthString(subFactorial/kinds_this_index,ints,k - (index - 1)*subFactorial,result,kinds_this_index);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值