错排问题--十二金钗

#每日一面BAT#第6题:金钗赛诗

每日一面BAT
赛诗会后,十二金钗待奔前程。
分别宴上,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(1)=0 只有一个元素的时候,怎么放都是原来的位置,所以没有错排的可能

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值