问题:给你一些不重复的元素,将它们从小到大排序,问你某个排列在所有的排列处于第几大;
康拓展开:公式为:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!(an是n这个数字在所有元素中排第几从0开始算,也就是有几个比n小的数字)
讲解:举个例子现在有4个元素为1,2,3,4,将他们从小到大排序结果如下:
①1 2 3 4 ⑦2 1 3 4 ⑬3 1 2 4 ⑲4 1 2 3
②1 2 4 3 ⑧2 1 4 3 ⑭3 1 4 2 ⑳4 1 3 2
③1 3 2 4 ⑨2 3 1 4 ⑮3 2 1 4 ㉑4 2 1 3
④1 3 4 2 ⑩2 3 4 1 ⑯3 2 4 1 ㉒4 2 3 1
⑤1 4 2 3 ⑪2 4 1 3 ⑰3 4 1 2 ㉓4 3 1 2
⑥1 4 3 2 ⑫2 4 3 1 ⑱3 4 2 1 ㉔4 3 2 1
现在问你4 2 1 3在这中序列中排第几位,大家是对照着上面的一眼就看出来了,如果没有这个表呢,如果数字再多几位呢,是不是感觉很难找到他的我位置了,而康拓展开只需要通过一些计算就可以算出来他的位置,而不需要排列出这些元素再去寻找;公式在上面;现在说一下为什么是这样呢;
就比如4 2 1 3这个序列
先看第一位4,比4小的数字有三个1,2,3,所以,以这三个数字开头的排列均小于它,3*(4-1)!为18,
(这一步中比4开头小的有1,2,3,以这三个数字开头,不论后面三个数字怎么排都不会大于它,这就是(4-1)!)
再看第二位2,比2小的数字有一位1,所以,从第二位开始以1开头的排列均小于它,1*(4-1-1)!为2,
(在4排在第一时(即第一步的情况下),这一步中比2开头的数字有一个1,以4 1的顺序排,不论后面怎么排都不会大于它,即(4-1-1)!)
再看第三位1,比1小的数字有零个,所以,0*(4-2-1)!为0,
再看第四位4,比3小的数字有两个1,2然而1,2都排好了所以比三小的数字为零,所以,0*(4-3-1)为0;
X=3*(4-1)+1*(4-1-1)!+0*(4-2-1)!+0*(4-3-1)!=20;
在它前面有20个比他小的,所以他就排在20+1的位置;
看到这应该对康拓展开差不多理解了把,那么代码该怎么写呢?
long long KT(string a)
{
long long sum=0,cnt,len=a.length();//sum为第几大,cnt为一个临时变量求比当前这个数字小的还有几个,len就是长度
for(int i=0;i<len;i++)
{
cnt=0;
for(int j=i+1;j<len;j++)//求cnt
{
if(s[j]<s[i]) cnt++;//在该数后面有几个比他小的数字,即没排的数字中有几个比它小的
}
sum+=cnt*f[len-i-1];//f[x]为x的阶乘
}
return sum;//返回有多少个比它小的排列
}
这有一道模板题大家可以看看,nwsoj1235:我排第几个(我博客有题解需要自找)