#每日一面BAT#第6题:金钗赛诗
每日一面BAT
赛诗会后,十二金钗待奔前程。
分别宴上,12人各写了一首诗放入宝囊。
大家随机取一个,若取到自己的诗,则再取一个并放回自己的诗。
12人都拿到诗算一种分配。
D(1)=0 只有一个元素的时候,怎么放都是原来的位置,所以没有错排的可能
递推公式可以推导出结果的数学表达式,不过我看那个表达式挺长的,而且真的需要计算结果的时候,也不是那么容易就能得到结果。
赛诗会后,十二金钗待奔前程。
分别宴上,12人各写了一首诗放入宝囊。
大家随机取一个,若取到自己的诗,则再取一个并放回自己的诗。
12人都拿到诗算一种分配。
问:共有多少种不同的分配?
问题来源:http://ask.julyedu.com/question/608?notification_id=31929&rf=false&item_id=2160,2164#!answer_2164
关于错排问题,百度百科有很清楚的解释(wiki也有。。。不过打不开/(ㄒoㄒ)/~~)
附上百度百科的链接:http://baike.baidu.com/view/668994.htm
既然百度百科都解释的很清楚了,我就不再多说废话了。说说我的做法。
以下黑体部分来自百度百科:
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.
D(2)=1 两个元素的时候,相互调换一下位置就可以得到一种错排,也仅有这一种错排。
好了,现在我们有了递推公式,同时也有了初始值,因此我们就可以写一个函数(此处用C++语言)来计算出n个元素的错排分配种类数。
代码如下:
int wrongSort(int n)
{
int f1 = 0; //D(1) = 0
int f2 = 1; //D(2) = 1
int Dn = 0;
if (n == 1)
{
Dn = f1;
}else if(n == 2)
{
Dn = f2;
}
for (int i = 3; i <= n; i++)
{
Dn = (i-1)*(f1+f2); //D(n) = (n-1) [D(n-2) + D(n-1)]
f1 = f2;
f2 = Dn;
}
return Dn;
}
递推公式可以推导出结果的数学表达式,不过我看那个表达式挺长的,而且真的需要计算结果的时候,也不是那么容易就能得到结果。
所以我就直接采用递推来计算。算法复杂度O(n)。时间复杂度T(n)