LeetCode: Permutation Sequence

思路分析

非常经典的排列问题。传统的暴力做法显然会超时,我们需要思考这道题目背后的数学规律。要求一串序列的任意第k个排列,显然不存在O(1)的算法能够一次推出。这样我们考虑能否一位一位地推出整个序列呢?显然我们可以得到规律,设第一位是第m个数字,则应该有:m=upper(k/(n-1)!)。这样,为了产生这样的第一位,我们消耗了多少次next_permutation呢?应该消耗了(m-1)*(n-1)!次。这样,问题就转化为对于除掉第一位后剩余的序列,求其第k-(m-1)*(n-1)!个排列。这样,问题就可以递归求解了。当然,这个递归可以轻易转换为循环,因为它本质上是尾递归。

代码

#define REP(i,a,b) for(int i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

class Solution {
public:
    string getPermutation(int n, int k) {
        string res(n, '0');
        int nums[10], fracs[10];
        int frac = 1;
        rep(i, n) {
            if ( i ) frac *= i;
            fracs[n - i - 1] = frac;
            nums[i] = i + 1;
        }
        rep(i, n) {
            int pos = (k - 1) / fracs[i];
            res[i] = nums[pos] + '0';
            REP(j, pos, n - i) nums[j] = nums[j + 1];
            k -= pos * fracs[i];
        }
        return res;
    }
};
comments powered by Disqus
Published:
2014-11-02
分类:
Tag: