身高排队算法-(较优解):12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?

本文探讨了一道阿里巴巴面试题,即12个人排成两排,每排从矮到高,第二排高于第一排。提出了一个算法思路,将问题转化为数字排列,通过++操作动态更新排列,并检查是否符合要求,提高了遍历效率。
摘要由CSDN通过智能技术生成

本人对解决算法有兴趣,曾在网上看到过一道阿里巴巴的面试题.

题目是这样的:12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?

 

所以自己也考虑了一个算法,也在网上看到别人的不同的算法。感觉我这个算法遍历效率很高,而且也很简洁(不敢用最来形容,怕强中更有强中手,当然如果能推导出公式来求解的话肯定会比我这个算法快,这个公式是F(n) = (n! / ((n/2)! * (n/2)!))/ (n/2 +1)).

我的算法思想是这样的:

(1)把排队的问题转换成数字排列问题,类似于0- 11这12个数排成2行。

(2)可以只考虑前一排的情况,因为只要前一排是符合某些条件,剩余的数按顺序放后排自然能满足条件。

(3)第一排数要符合的条件是:

下面数值表示的是位置,

0   1   2   3   4   5

6   7   8   9 10 11

 

对于位置0,可能的数的范围是0

对于位置1,可能的数的范围是1,2

对于位置2,可能的数的范围是2,3,4

对于位置3,可能的数的范围是3,4,5,6

对于位置4,可能的数的范围是4,5,6,7,8

对于位置5,可能的数的范围是5,6,7,8,9,10

这样可以推导出:

对于位置为n的数,其数的范围是[n, 2n].

这样对于0-5的位置的数的范围就是[{0,1,2,3,4,5}, {0,2,4,6,8,10}],

我们把这个0-5的位置的数当成一个大的数来看待,对其进行++操作,只不过进位的时候是按每个位置的数的范围来进行进位。

比如:

1.目前数是{0,1,2,3,4,5}, ++操作后,数变为{0,1,2,3,4,6},因为6小于且等于位置5的最大值2n = 10,所以此组合是个符合要求的组合。

2.又如目前数是{0,1,2,3,4,10}, ++操作后,数变为{0,1,2,3,4,11},因为11大于位置5的最大值2n = 10, 因此要进位,这样位置4的数++,再检查位置4的数++后是5,小于且等于位置4的最大值2n = 8,这个位置符合条件,而位置5的数要置"0",这个0不能是再从范围的起始值开始,而是要等于位置4的数+1.因为从起始值开始的数肯定是小于位置4的值的。

3.以此类推,如果目前数是{0,1,4,6,8,10},++操作后,需要进位,一步一步往前进位,最终进位位置1的数,数就变成了{0,2,5,7,9,11},然后要把位置1之后位置的每个位置的数置"0", 等于前一个位置的数+1,这样最后数就是{0,2,3,4,5,6}.

4.检查此数组合是否符合条件是,检查最后一个数是否小于且等于其位置的最大值。

附算法如下:

#include <iostream>

#include <vector>

 

using namespace std;

 

class pai2dui

{

public:

    pai2dui(int n)

    :mMaxNum(n / 2)

    ,mCount(0)

    ,mAllCount(0)

    {

        if (n > 1)

        {

            mCount = 1;

            for(

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值