算法:排列的字典序问题
作者:互联网
排列的字典序问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
Submit Statistic
Problem Description
n个元素{1,2,……, n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下:
给定n以及n个元素{1,2,……, n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。
Input
输入数据的第1行是元素个数n(n≤20)。接下来的1行是n个元素{1,2,……, n }的一个排列。
Output
输出数据的第1行是字典序值,第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!,,,依次类推。。。
看例子:
tot=0;
比2小的数有1个,则 tot+=1*7!;
比6小的数有4个,则 tot+=4*6!;
比4小的数有2个,则 tot+=2*5!;
比5小的数有2个,则 tot+=2*4!;
比8小的数有3个,则 tot+=3*3!;
比1小的数有0个,则 tot+=0*2!;
比7小的数有1个,则 tot+=1*1!;
比3小的数没有;
(注:在排列中,求比某个数小的数的个数时,排除之前出现过的数)
如何得到2 6 4 5 8 1 7 3的下一个排列?
1 从尾部往前找第一个P(i-1) < P(i)的位置
2 6 4 4 5 8 1 <-- 7 <-- 3
最终找到1是第一个变小的数字,记录下1的位置i-1
2 从尾部往前找到第一个大于1的数
2 6 4 4 5 8 1 7 3 <--
最终找到3的位置,记录位置为m
3 交换位置i-1和m的值
2 6 4 4 5 8 3 7 1
4 倒序i位置后的所有数据
2 6 4 4 5 8 3 1 7
可以用 next_permutation(data,data+n);
#include <bits/stdc++.h>
using namespace std;
//求阶乘
int fib(int n)
{
if(n<=1)
return 1;
else
{
return fib(n-1)*n;
}
}
//字典序,从0开始
int order(int data[],int n)
{
int ret = 0;
for(int i=0; i<n; i++)
{
int m = data[i];
int cnt = 0;
for(int j=i; j<n; j++)
{
if(m>data[j])
cnt++;
}
ret+=cnt*fib(n-i-1);
}
return ret;
}
void swap(int data[], int i, int j)
{
int t = data[i];
data[i] = data[j];
data[j] = t;
}
void reverse(int a[],int min,int n)
{//数组逆置
int i,j,temp;
for(i=min,j=n-1;i<j;i++,j--)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
void next_perm(int data[],int n)
{//求出下一个字典序
int min,max;
for(int i=n-1;i>=0;i--)
{//找出升序截止点的数组下标
if(data[i-1]<data[i])
{
min=i-1;
break;
}
}
for(int i=n-1;i>=0;i--)
{//找出刚刚比a[min]大的数
if(data[i]>data[min])
{
max=i;
break;
}
}
swap(data[min],data[max]);
reverse(data,min+1,n);//注意交换的是a[min+1]到a[n]
}
int main()
{
int n;
cin>>n;
int data[1000];
for(int i=0; i<n; i++)
cin>>data[i];
cout<<order(data,n)<<endl;
next_perm(data,n);
// next_permutation(data, data + n);
for(int i=0; i<n; i++)
{
cout<<data[i]<<" ";
}
cout<<endl;
return 0;
}
运行效果:
标签:排列,int,tot,算法,数有,data,字典 来源: https://blog.csdn.net/wl1780852311/article/details/100834712