记录我的学习与生活
玩踢猴子的一个约瑟夫算法
首先就给出题目了,大家先看看
一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,
从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,
直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n,
输出最后那个大王的编号
这个题目是我面试的公司给出的一个题目,不要标准答案,要求有自己的想法,还允许有错误,\(^o^)/~
这道题杀死我N个脑细胞,刚开始写了一种算法,在一些特定的条件下总是导致踢猴子位置的获取错误
最终还是解决了,函数如下
function getKing($n, $m){
//强制转换为数值型
$n = intval($n);
$m = intval($m);//让猴子排好队
for($i=0; $i < $n; $i++){
$monkeys[$i] = $i+1;
}$start = 0;//初始化开始位置
$step = $m – 1;
for($i=0; $i < $n; $i++){
//判断猴子的个数,如果只剩一个就直接返回这只猴子
$num_monkey = count($monkeys);
if($num_monkey === 1) return $monkeys[0];//如果这一圈找不到要踢的猴子,就在下一圈找到要踢的猴子
if($start + $step >= $num_monkey){
$start = ($step+$start)%$num_monkey;
}
else{ //这一圈找到就直接踢它
$start = $start + $step;
}unset($monkeys[$start]); //踢猴子
sort($monkeys); //让猴子重新站好
}
}
算法的思想就是,循环链表,但是我始终让猴子永远排成一横队,这样觉得更容易理解一点
猴子始终排成整齐的一排,中间不允许有空余的位置。
如果不用回头就能找到可以踢走的猴子,那就不回头一直在这一排往下踢
如果找了好长时间,找不到可以踢的猴子,我们还是不回头
而是重新开始从这排猴子的第一个开始找,这时候重要的是,这时候踢哪一个?
我们上次找猴子虽然没有找到,但是我们的花的功夫可不能白搭是吧,我们接着上次在找,我们知道还有几个猴子没有点名就行了,接着上一轮继续点,找到猴子,把它踢出去。
就是这样,一直循环下去,我踢踢踢,国王是不能踢的,等到踢不动了,就找到猴王了。
网上看到牛人写的算法,佩服
function kickMonkey ($n,$m) {
$s = 0;
for ($i=2; $i <=$n; $i++) {
$s = ($s+$m)%$i;
}
$win = $s+1;
return $win;
}
算法简化了很多,我还没有消化掉。
2009年07月20日 - 3:31 上午
挺好玩~呵呵
[回复]
2009年07月20日 - 3:03 下午
假设编号为0,1,2,..(n-1)。M是定值,只考虑一次剔除过程。
if(n==1) f(n)=0;
else f(n)=( f(n-1)+m)%n;
考虑递归式时,只关注规模减少过程,不关注子问题如何解,能到达递归出口就行。个人理解…
[回复]
2009年07月21日 - 1:36 下午
有时候也对自己感叹:人和人差距咋那么大捏!
[回复]
2009年07月22日 - 4:38 上午
@TaoGOGO 出去玩了两天
@细毛 我不我咋说是牛人啊
@Keengle 用数学的算法就是简化了很多
@ngshaozhu 一山更一山高啊
[回复]
2009年07月19日 - 7:39 上午
你对程序语言的解释方式很有意思,向你学习
[回复]
2009年07月19日 - 7:47 上午
@卢松松 互相学习了,我觉得编程解决的就是生活上的问题,解决它的时候不要把它想成程序,想象一下如果让我们用手的话怎么解决,然后用程序实现它。
[回复]
2009年07月19日 - 12:55 下午
最近 谷歌相册打不开了 郁闷!
[回复]
2009年07月20日 - 6:46 上午
- -怎么牛人的跟你一比少了这么多
[回复]