小小程序媛  
得之坦然,失之淡然,顺其自然,争其必然

题目

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.

分析

首先想到的是,采用STL库中的标准算法next_permutation(),寻找第k个排列即可,可是提交结果为Time Limited Exceed,显然,必须寻找更优算法。

借鉴了别人的思想,设计如下(原文博客):

数学解法

在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。

假设有n个元素,第K个permutation是

a1, a2, a3, ….. …, an

那么a1是哪一个数字呢?

那么这里,我们把a1去掉,那么剩下的permutation为

a2, a3, …. …. an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道

设变量K1 = K

a1 = K1 / (n-1)!

同理,a2的值可以推导为

a2 = K2 / (n-2)!

K2 = K1 % (n-1)!
…….

a(n-1) = K(n-1) / 1!

K(n-1) = K(n-2) /2!

an = K(n-1)

STL标准算法实现(Time Limited Exceed)

class Solution {
public:
    string getPermutation(int n, int k) {
        if (n <= 0 || k <= 0 || k > factorial(n))
            return "";

        vector<int> v;
        for (int i = 1; i <= n; i++)
            v.push_back(i);

        int index = 1;
        while (index < k && next_permutation(v.begin(), v.end()))
            index++;

        string str = "";
        for (int i = 0; i < n; i++)
            str += IntToStr(v[i]);
        str += '\0';

        return str;

    }

    string IntToStr(int n)
    {
        string str = "";

        while (n != 0)
        {
            str += (n % 10 + '0');
            n /= 10;
        }

        reverse(str.begin(), str.end());

        return str;
    }

    long factorial(int n)
    {
        if (n <= 1)
            return 1;
        else
            return n * factorial(n - 1);
    }
};

AC代码

class Solution {
public:

    string getPermutation(int n, int k) {
        vector<int> nums(n);

        int pCount = 1;
        for (int i = 0; i < n; ++i) {
            nums[i] = i + 1;
            pCount *= (i + 1);
        }

        k--;
        string res = "";
        for (int i = 0; i < n; i++) {
            pCount = pCount / (n - i);
            int selected = k / pCount;
            res += ('0' + nums[selected]);

            for (int j = selected; j < n - i - 1; j++)
                nums[j] = nums[j + 1];
            k = k % pCount;
        }
        return res;
    }

};

GitHub测试程序源码

posted on 2015-09-07 20:06  Coding菌  阅读(147)  评论(0编辑  收藏  举报