一类反复取元素问题的递归解

问题1:N个人排成一个排,从第一个人开始依次报数,数到K的人则退出,接下来的人继续从1开始数数,最右边的人数完数后最左边的人作为后继接着数,形成一个逻辑的环,如此反复直至最后一人,求最后一个人的位置索引

 

问题2:N个人排成一排,第一次所有从1开始的间隔为2的位置的人退出(1、3、5……),然后在剩下的一排人中,第二次所有从1开始间隔为3的位置的人退出(1、4、7……),间隔依次递增4、5、6……,依次直至最后一个人,求最后一个人的位置索引

 

 

 

问题1分析:第一个退出的人位于Q=(K-1)%N+1的位置,然后将Q之前所有人平移到右端,于是变成了一个N-1长度的子问题,假设第二次退出的人位于新队列的P位,现在分析新队列的P位“映射”到旧队列(Q位之前所有人移动前的队列)的位置。如图简示:

 

第一例,假设N=8,K=6,则第1次队列呈现 XXXXXX XX, 位于第Q=(6-1)%8+1=6位的红色人员退出,紫色人员构成Q位之前的队伍,蓝色人员构成Q之后的队伍,经过紫色人员平移至右端得新队列 XX XXXXX 第2次 位于新队列第6位的红色人员退出 XX XXXX X ,通过对比,得知退出人员位于紫色队列得第4位,也即实际位于第一次队列的第4位

 

又一例,假设N=8,K=3,则第1次队列呈现 XXX XXXXX,位于第Q=(3-1)%8+1=3位的红色人员退出,并将紫色人员平移至右端形成新队列 XXXXX XX ,第2次位于新队列的第3位红色人员退出 XXX XX XX ,通过对比得知是原Q位之后的蓝色人员的第3位,也即第1个队列的第6位。

 

由此,可以得到一个由第i次队列到第i-1次队列的索引的映射关系,设定P位第i次队列的退出人员位置,其对应到第i-1次队列的位置为:

如果P<=N-Q,则新位置P‘=P+Q

如果P>N-Q,则新位置P'=P-(N-Q)

有了这个映射关系,就可以得到一个比较快速的如下递归解

 

 

 

问题2分析:思路类似,不同的仅仅是第i层到第i+1层时人数的转换,以及由第i+1层位置索引映射回第i层索引的计算方法稍有区别。问题2里面,如果在第i层是N个人中间去掉间隔步长为K的人,第i层将有(N-1+K)/K个人退出,进而转化成第i+1层子问题:N-(N-1+K)/K个人中去掉间隔步长K+1的人。如果第i+1层返回问题的解为P,则映射到第i层的位置应该是P+(P-1+K-1)/(K-1),意味着要把P前面的在第i层就被去掉的人补回来后才能得到P在第i层对应的位置。

 

于是得如下实现,对与N个人的问题2,调用函数positionFast(N,2)可得到最后退出的人位置

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值