Leetcode permutation-sequence

题目描述

集合[1,2,3,…,n]一共有n!种不同的排列

按字典序列出所有的排列并且给这些排列标上序号

我们就会得到以下的序列(以n=3为例)

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

现在给出n和k,请返回第k个排列

注意:n在1到9之间

 

首先解决一个问题  那就是任意给定一个排列数 ,其后面一个next_permutation是多少

 

基本思路:

由于是下一个排列数一定比之前的大,通过后面较大的数与前面较小的数交换得到

那么只需要使得交换后增大的那一位的位数尽可能往后即可

  1. 即通过从后往前遍历到第一个减小的数  那么它既是交换位置pos
  2. 那么还需要一个数字,通过寻找pos之后比A[pos]大的最小的数,使得增大的尽可能小即可
  3. 交换之后,该数字比前一个数更大(pos位置更大了,前面数不变)
  4. 最后,pos之后的数字进行从小到大排序即可(确保之后的数最小)

 

string next_fun(string num)
    {
        int size=num.size();   
        int p=size-2;
        while(p>=0 && num[p]>num[p+1])  //定位到第一个减小的位置
            p--;   
        if(p==-1)  //说明整个为一个递减序列
            return num;  //不存在下一个序列
        int swap_pos=p;//交换的位置
        p++;
        while(pnum[swap_pos])  //找到后面比num[swap]大的最小的数
            p++;
        //另一个交换位置为p-1  
        char tmp=num[swap_pos];
        num[swap_pos]=num[p-1];
        num[p-1]=tmp;
        sort(num.begin()+swap_pos+1,num.end());//剩余元素排序
        return num;
        
    }

 

而本题所求为求解N的第K个排列数

容易知道N的排列数共有n!个

而以1开头的排列数有(n-1)!个

以2开头的排列数也有(n-1)!个

。。。。。

求解第K个  一种优化策略先定位到其第一个数字m是多少。从以m开头最小的排列数开始向后 next操作(K-num)次

其中num是前面m-1个首位数字的排列数

易错点: k恰好能被(n-1)!整除的时候

    string getPermutation(int n, int k) {
        // write code here
        if(n==1)
            return string("1");
        int num=1;
        for(int i=1;i<=n-1;i++)
            num*=i;
        //以1打头的排列数有num个  (n-1)!
        int pre=k/num;//跳过的首字母个数
        int dev=k%num;//偏移
        if(dev==0)
        {
            //易错点  若被整除  需要单独考虑
            pre--;
            dev=num;
        }
        char first_num='1'+pre;
        string str;
        str+=first_num;
        for(int i=1;i<=n;i++)
        {
            if(first_num!=('0'+i)) //跳过首字母
                str+=('0'+i);
        }
        
        //str为以first_num为首个数字的第一个排列数
        //再往后执行dev-1次偏移next即可
        for(int i=0;i

 

你可能感兴趣的:(Leetcode)