1. 程式人生 > >排列的字典序問題

排列的字典序問題

問題描述:
n個元素{1,2,, n }有n!個不同的排列。將這n!個排列按字典序排列,並編號為0,1,…,
n!-1。每個排列的編號為其字典序值。例如,當n=3時,6 個不同排列的字典序值如下:


字典序值 0 1 2 3 4 5
排列 123 132 213 231 312 321

演算法設計:
給定n以及n個元素{1,2,, n }的一個排列,計算出這個排列的字典序值,以及按字典
序排列的下一個排列。

資料輸入:
輸出元素個數n。接下來的1 行是n個元素
{1,2,, n }的一個排列。

結果輸出:
將計算出的排列的字典序值和按字典序排列的下一個排列輸出。第一行是字典序值,第2行是按字典序排列的下一個排列。

Sample Input

8
2 6 4 5 8 1 7 3

Sample Output

8227
2 6 4 5 8 3 1 7

程式碼僅供參考,勿拷貝作為課堂派作業!!!

題意:給出一個序列,求這個序列是全排列中的第幾個,以及求出下一個排列。。。

思路:

         我們可以從從開始算,因為不能有重複,以1開頭的後面有7位數有1*7!,然後以2開頭的後面有六位數,但第二位要小於6,即有1、3、4、5滿足,有4*6!,然後以26...開頭的後面有5位數,要求第三位要小於4,即有1,3滿足,有2*5!,,,依次類推。。。
        找到規律為:看後面有幾個比當前數小的,,比如2後面比2小的只有1,6後面比6小的有4個,4後面比4小的有2個。。即:

        

然後說一下STL庫中的next_permutation和prev

_permutation,前者是求當前排列按照字典序排列的下一個排列,後者是求前一個排列。。。

程式碼:

#include<stdio.h>
#include <algorithm>
#define ll long long
using namespace std;

int f(int n)
{
    if(n==1)
        return 1;
    return n*f(n-1);
}
int main()
{
    ll n,i,j;
    ll a[1000];
    ll sum=0;
    while(scanf("%I64d",&n))
    {
        for(i=0;i<n;i++)
            scanf("%I64d",&a[i]);
        for(i=0;i<n-1;i++)
        {
            ll count=0;
            for(j=i+1;j<n;j++)
                {
                    if(a[j]<a[i])
                        count++;
                }
                sum+=(count*f(n-i-1));
        }
        printf("%I64d\n",sum);
        if(next_permutation(a,a+n))
        {
            for(int i=0;i<n;i++)
                printf("%I64d ",a[i]);
                printf("\n");
        }
    }
    return 0;
}