《PHP程序员面试算法宝典》读书笔记01——经典算法题

第1章 经典算法题

1.1 有多少苹果用来分赃

题目描述:

有5个人偷了一堆苹果,他们准备在第二天进行分赃。晚上,有个人溜出来,把苹果分成5份,将多余的一个扔给了树上的猴子,自己先将1/5藏了起来。其他4个人也都像第一个人那样,将苹果分成5份,将多余的一个扔给树上的猴子,偷走了1/5。第二天,大家分赃,也是分成5份,将多余的一个扔给猴子,最后一人分了一份。问:共有多少个苹果?

分析与解答:

假设总的苹果数量为s,上一个人对苹果划分时剩余的苹果数量为y,则有y=s-s/5-1。从这个公式开始,第一个人分的苹果总数s为最初的苹果总数,第二个人开始分赃直到结束分赃时,这个s都为上一个人分完剩余的苹果数量。以此类推。

<?php
/**
 * 1.有多少苹果用来分赃
 * 5人偷了一堆苹果,准备第二天分赃。晚上,一人偷偷将苹果分成5份,多的一个给了猴,自己藏了1/5。
 * 剩下的其他4个人,也同样这么想的,都像第一个人那样,将剩下的苹果分成5份,多的一个给猴,藏1/5。
 * 最后一人分了一份。问:苹果几何?
 */
for($s = 5; ; $s++) {
   
    if($s % 5 == 1 ) {
   
        $m = $s - round($s/5) - 1; // round()函数对浮点数进行四舍五入
        if($m % 5 == 1) {
   
            $n = $m - round($m/5) - 1;
            if($n % 5 == 1) {
   
                $k = $n - round($n/5) - 1;
                if($k % 5 == 1) {
   
                    $x = $k - round($k/5) - 1;
                    if($x % 5 == 1) {
   
                        $y = $x - round($x/5) - 1;
                        if($y % 5 == 1) {
   
                            echo $s;
                            exit();
                        }
                    }
                }
            }
        }
    }
}
?>
// 15621

1.2 选猴王

题目描述:

群猴排成圈,按1~n依次编号。从第1只开始数,数到第m只,第m只猴出圈。从第m+1只开始,数到第m只,该猴出圈。以此类推,最后剩下一只猴,即可成为新任猴王。编程模拟此过程,输入m、n,输出猴王编号。

分析与解答:

首先将猴从1~n编号存放到数组中,对猴子的总个数进行循环,循环时将数到编号的猴子从数组删除,将未数到的猴子从原位置移到数组末尾,移动后需将原位置的编号删除。只要判断该编号数组个数大于1都继续循环,直到数组最后只剩下一个编号,这个编号则为猴王。

<?php
header("Content-type:text/html;charset=utf-8");
function monkeyKing($n, $m) {
   
    $monkeys = range(1, $n);
    $i = 0;
    $k = $n;
    while(count($monkeys) > 1) {
   
        if(($i+1) % $m == 0) {
   
            unset($monkeys[$i]);
        } else {
   
            array_push($monkeys, $monkeys[$i]);
            unset($monkeys[$i]);
        }
        $i++;
    }
    return current($monkeys);
}
$monkey = monkeyKing(5, 2);
echo "最后当猴王的猴子编号为:",$monkey; // 最后当猴王的猴子编号为:3
?>

1.3 移动多少盘子才能完成汉诺塔游戏(递归)

题目描述:

汉诺塔游戏规则如下:

1)有三根柱子A、B、C,A柱上有若干盘子;

2)每次移动一只盘子,只能把小的盘子叠在大的盘子上面;

3)把所有盘子从A柱移到C柱上;

4)经研究发现,汉诺塔的破解很简单,就是按照移动规则向一个方向移动盘子。

5)例如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C。共移动7次。

实现代码:

<?php
function hanou($n, $x, $y, $z) {
   
    if($n == 1) {
   
        echo '移动盘子 1 从 '.$x. ' 到 '.$z."\n";
    } else {
   
        hanou($n-1, $x, $z, $y);
        echo "移动盘子 $n$x$z\n";
        hanou($n-1, $y, $x, $z);
    }
}
hanou(3, 'A', 'B', 'C');
?>

控制台输出:

移动盘子 1 从 A 到 C
移动盘子 2 从 A 到 B
移动盘子 1 从 C 到 B
移动盘子 3 从 A 到 C
移动盘子 1 从 B 到 A
移动盘子 2 从 B 到 C
移动盘子 1 从 A 到 C

1.4 约瑟夫环

题目描述:

Josephus和他的朋友及另外39个犹太人共41个人排成一圈,从第一个人开始报数,每报道第三个人该人就必须自杀,然后由下一个人从1重新开始报数,直到所有人都自杀身亡为止。然而Josephus和他的朋友并不想遵守规则,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

分析与解答:

使用程序来求解的话,只要将阵列当作环状来处理,在阵列中由计数1开始,每3个数得到一个计数,直到计数到41为止;然后将阵列由索引1开始列出,就可以得知每个位置的自杀顺序,这就是约瑟夫排列。41个人报数的约瑟夫排列(自杀顺序)如下表所示:

排列顺序 1 2 3 4 5 6 7 8 9 10
自杀顺序 14 36 1 38 15 2 24 30 3 16
排列顺序 11 12 13 14 15 16 17 18 19 20
自杀顺序 34 4 25 17 5 40 31 6 18 26
排列顺序 21 22 23 24 25 26 27 28 29 30
自杀顺序 7 37 19 8 35 27 9 20 32 10
排列顺序 31 32 33 34 35 36 37 38 39 40
自杀顺序 41 21 11 28 39 12 22 33 13 29
排列顺序 41
自杀顺序 23

实现代码:

<?php
header("content-type:text/html;charset=utf-8");
define("N",41); // 参与总人数
define("M",3); // 每到3自杀一人

$man = array(0);
$count = 1;
$i = 0;
$pos = -1;
$alive = 2; // 想救的人数
while($count <= N) {
   
    do{
   
        $pos = ($pos+1)%N; // 环状处理
        if(@$man[$pos] == 0) {
   
            $i++;
        }
        if($i == M) {
   
            $i = 0; // $i重置
            break;
        }
    } while(1);
    $man[$pos] = $count;
    $count++;
}
// 截取出对应最大键值对应的键名
arsort($man);
$arr = array_slice($man, 0, $alive, true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦里逆天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值