LeetCode 60 Permutation Sequence

200 阅读2分钟

LeetCode 60 Permutation Sequence

思路

  1. 采用Next Permutation的方法。

  2. 不难发现,总共有n!个permutation。按照第一个元素的值将permutation划分为不同的组,可见每组有(n-1)!个permutation。那么考虑通过这一特性,直接确定每个位置的值。以n为4,k为9,结果为2314举例。首先新建vector{1,2,3,4},根据第一个位置的值,将permutation分为4组,每组有3!个permutation。考虑到k为6的结果的第一个位置的值其实还是1,我们可以将k在一开始减1。令i = k/6,我们直接取数组中第i个元素作为第一个位置的结果。故,k变为8,8/6=1,那么第一个位置的值为2,再在数组中将2删掉,那么数组变为[1,3,4]。调整k:k = k - 1 * 6 = 2。重复之前的过程即可。这时,每组的大小为2!,那么k/2 = 2/2 = 1,因此,第二个位置的值为3。将其从数组中删掉,那么数组为[1,4]。调整k:k = k - 1 * 2 = 0。这时,每组的大小为1!,那么k/1 = 0/1 = 0。因此,第三个位置的值为1,将其从数组中删掉。调整k:k = k - 0 * 1 = 0。这时,每组的大小为1,处理同上。

代码

第一种方法

class Solution {
public:
    string getPermutation(int n, int k) {
        vector<char> sequence(n);
        for (int i = 0; i < n; ++i)
            sequence[i] = i+ '1';
        
        for (int i = 1; i < k; ++i) 
            nextPermutation(sequence);
        
        string rs;
        for (const auto &ch : sequence)
            rs += ch;
        return rs;
    }
    
    void nextPermutation(vector<char> &sequence) {
        int i, j;
        for (i = sequence.size() - 2; i >= 0; --i)
            if (sequence[i] < sequence[i+1]) break;
        
        for (j = sequence.size() - 1; j > i; --j)
            if (sequence[j] > sequence[i]) break;
        
        swap(sequence[i], sequence[j]);
        
        reverse(sequence.begin() + i + 1, sequence.end());
    }
};

第二种方法

class Solution {
public:
    string getPermutation(int n, int k) {
        int divider, i;
        vector<char> vec;
        string str;
        
        for (int i = 0; i < n; ++i) vec.push_back(i + '1');
        
        --k;
        while (n) {
            for (i = 1, divider = 1; i < n; ++i)
                divider *= i;
            
            i = k / divider;
            k -= i * divider;
            
            str += vec[i];
            vec.erase(vec.begin() + i);
            
            --n;
        }
        
        
        return str;
    }
};