排列序列的计算

时间:2015-11-06 22:29:25

标签: c++ algorithm

我正在处理下面的问题和发布的代码我正在调试和问题陈述。实际上我试图找到一些参考解决方案,所有都是相似的,没有太多的解释。如果有人可以帮助解释逻辑如何工作,那将是伟大的。我特别感到困惑的是" for(i = 0,k - ; i

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.

代码参考,

#include <iostream>
using namespace std;

string getPermutation(int n, int k) {
    int i,j,f=1;
    // left part of s is partially formed permutation, right part is the leftover chars.
    string s(n,'0');
    for(i=1;i<=n;i++){
        f*=i;
        s[i-1]+=i; // make s become 1234...n
    }
    for(i=0,k--;i<n;i++){
        f/=n-i;
        j=i+k/f; // calculate index of char to put at s[i]
        char c=s[j];
        // remove c by shifting to cover up (adjust the right part).
        for(;j>i;j--)
            s[j]=s[j-1];
        k%=f;
        s[i]=c;
    }
    return s;
}

int main(int argc, const char * argv[])
{

    // insert code here...
    std::cout << getPermutation(4, 5) << endl;
    return 0;
}

发布另一个更清晰的实现,

def kthperm(S, k):  #  nonrecursive version
    P = []
    while S != []:
        f = factorial(len(S)-1)
        i = int(floor(k/f))
        x = S[i]
        k = k%f
        P.append(x)
        S = S[:i] + S[i+1:]
    return P

1 个答案:

答案 0 :(得分:2)

问题陈述在排列的 lexical 排序中要求N个元素的Kth排列。

代码实现了一个非常好的算法,它按顺序直接生成Kth排列的元素,如下所示(伪代码):

GenerateKthPermutation(Set elements, int k)
{
    if (elements.size()==1)
    {
       output(elements.getOnlyElement());
       return;
    }
    int n = elements.size();

    //there are n! permutations of elements
    //no matter which one we choose as the _first_ element, there
    //will be (n-1)! permutations of the remaining elements.
    //The complete lexical ordering of permutations consists of:
    //(n-1)! permutations that start with the smallest element, then
    //(n-1)! permutations that start with the second smallest element, then
    //(n-1)! permutations that start with the 3rd smallest element, etc.
    //so the FIRST element in the (0-indexed) kth permutation, is the
    //(0-indexed) floor(k/(n-1)!)th-largest element

    int j = floor((k-1)/(n-1)!); //k-1, because the parameter is 1-indexed
    //removeJthLargest(0) removes and returns the smallest element
    //removeJthLargest(1) removes and returns the second-smallest
    //etc.
    output(elements.removeJthLargest(j));

    //now output the correct permutation of remaining elements.
    //we've skipped j*(n-1)! permutations, so subtract that from k
    k -= j*(n-1)!;

    //remember elements is 1 smaller now.
    //in real life you would iterate here instead of recursing
    GenerateKthPermutation(elements, k);
}

我希望能让事情变得清晰。要在评论中专门回答您的问题:

原始逻辑使用排序字符串来存储元素集。说&#34;通过移动来移除c的部分...&#34;是我说&#34; elements.removeJthLargest(j)&#34;的部分。它从字符串中删除了正确的元素,并将剩余的元素移动到一个新的,更小但仍然排序的字符串。