排列顺序的计算 [英] calculation of permutation sequence

查看:115
本文介绍了排列顺序的计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在下面的问题和后code我调试和问题的声明。其实我试着找了几个参考的解决方案,而且都没有过多的解释类似。如果有人可以帮助解释如下逻辑的作品,这将是巨大的。我用为(i = 0,K循环特别是困惑 - ;我

 集合[1,2,3,...,N]共包含n个!独特的排列。

通过上市,才能标注所有的排列,
我们得到如下序列(即,对于n = 3):

123
132
213
231
312
321
由于氮,钾,返回的第k个排列顺序。

注:给定n为9(含)之间1和。
 

code基准

 的#include<的iostream>
使用名字空间std;

字符串getPermutation(INT N,INT K){
    INT I,J,F = 1;
    第//左边是部分形成置换,右边是剩下的字符。
    串S(N,'0');
    对于(i = 1; I< = N;我++){
        F * =我;
        S [I-1] + = I; //使小号成为1234 ... N
    }
    为(ⅰ= 0中,k  - ;我n种;我++){
        F / = N-I;
        J = I + K / F; //计算字符的指数将在S [I]
        焦炭C = S [J]。
        //通过转移来掩盖(调整右侧部分)删除℃。
        对于(; J>我; j--)
            S [J] = S [J-1]。
        ķ%= F;
        S [i] = C;
    }
    返回S;
}

INT主(INT ARGC,为const char * argv的[])
{

    //插入code在这里...
    性病::法院<< getPermutation(4,5)&其中;&其中; ENDL;
    返回0;
}
 

发表另一种实现方式哪个更清晰可读,

 高清kthperm(S,K):#非递归版本
    P = []
    而S = []!
        F =阶乘(LEN(S)-1)
        I = INT(楼(K / F))
        X = S [i]于
        k = k%F
        P.append(X)
        S = S [我] + S [I + 1:]
    返回P
 

解决方案

这个问题的语句请求N个元素的第k个排列,在词汇的的排列排序。

在code实现了一个非常漂亮的算法,直接产生第K个置换的元素,为了像这样(伪code):

  GenerateKthPermutation(集合中的元素,诠释K)
{
    如果(elements.size()== 1)
    {
       输出(elements.getOnlyElement());
       返回;
    }
    INT N = elements.size();

    //有n!元素的排列
    //无论我们选择的_first_元素其中之一,有
    //将第(n-1)!剩余的元素的排列。
    //排列的完整词汇顺序包括:
    //第(n-1)!排列开始的最小的元素,然后
    //第(n-1)!置换开始的第二小的元素,然后
    //第(n-1)!开始的第三最小元素等置换
    //所以在(0索引)第k个排列的第一要素,是
    //(0索引)地板(K /(N-1)!)个大要素

    诠释J =地板((K-1)/(N-1)!); // k-1个,由于参数是1索引
    // removeJthLargest(0)移除并返回最小的元素
    // removeJthLargest(1)移除并返回的第二小
    //等等。
    输出(elements.removeJthLargest(J));

    //现在输出剩余元素的正确排列。
    //我们跳过Ĵ*(N-1)!排列,所以减去给K
    的k  -  = j的*(N-1);!

    //记得元素1小了。
    //在现实生活中,你会在这里重复递归代替
    GenerateKthPermutation(元素,K);
}
 

我希望让事情说清楚。要具体回答你的问题的意见:

原逻辑使用的排序字符串来存储所述一组元素。部分,上面写着通过转移删除ç......就是我说的elements.removeJthLargest(十)的一部分。它消除了正确的元素从字符串并且将其余的做一个新的,规模较小,但仍然排序的字符串。

I am working on below problem and post code I am debugging and the problem statement. Actually I tried to find a few reference solutions, and all are similar without too much explanation. If anyone could help to explain how below logic works, it will be great. I am confused especially by the loop of "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.

Code reference,

#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;
}

Post another implementation which is more clear to read,

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

解决方案

The problem statement asks for the Kth permutation of N elements, in the lexical ordering of the permutations.

The code implements a very nice algorithm that generates the elements of the Kth permutation directly, in order, like this (pseudo-code):

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);
}

I hope that makes things clear. To specifically answer your question in comments:

The original logic uses a sorted string to store the set of elements. the part that says "remove c by shifting..." is the part where I say "elements.removeJthLargest(j)". It removes the proper element from the string and shifts the remaining ones to make a new, smaller, but still-sorted string.

这篇关于排列顺序的计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆