记录我的学习与生活
Posts tagged 算法
玩踢猴子的一个约瑟夫算法
七 19th
首先就给出题目了,大家先看看
一群猴子排成一圈,按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;
}
算法简化了很多,我还没有消化掉。