《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)
├──Package │ ├── Sort 排序篇 │ │ ├── BubbleSort.php 冒泡排序 │ │ ├── HeapSort.php 堆排序 大根堆 │ │ ├── MBaseSort.php 基数排序 MSD │ │ ├── LBaseSort.php 基数排序 LSD │ │ ├── QuickSort.php 快速排序 │ │ ├── ShuttleSort.php 飞梭排序 │ │ ├── ShellSort.php 希尔排序 │ │ ├── MergeSort.php 归并排序 │ │ ├── InsertSort.php 插入排序 │ │ └── SelectSort.php 选择排序 │ │ │ ├── Query 查找篇 │ │ ├── BinaryQuery.php 二分查找 │ │ ├── InseertQuery.php 插入查找 │ │ ├── FibonacciQuery.php 斐波那契查找 │ │ ├── BFSQuery.php 广度优先查找 │ ├── Kmp.php 算法导论-KMP算法 │ ├── DijkstraQuery.php 迪克斯特拉算法 │ │ └── QulickQuery.php 快速查找 │ │ │ ├── Structure 数据结构 │ │ ├── StackExample.php 堆栈 先进后出 LIFO (Last In First Out) │ │ ├── LinearChain.php 线性表 单链存储 │ │ └── LinearOrder.php 线性表 顺序存储 │ │ └── BinarySearchTree.php 二叉搜索树 │ │ │ ├── Tools 小工具集 │ │ └── SystemSwitch.php 堆栈实现进制转换 │ │ │ └── Other 其他 │ ├── MonkeyKing.php 约瑟夫环 │ ├── DynamicProgramming.php 动态规划 │ ├── Fibonacci.php 斐波那契数列 │ ├── StealingApples.php 偷苹果求余 │ ├── HanoiGames.php 汉诺塔游戏 │ ├── BidirectionalQueue.php 双向队列 │ ├── ColorBricks.php 彩色砖块 │ ├── GetCattle.php 牛年求牛 │ ├── OnlyNumbers.php 求唯一数 │ ├── PokerGames.php 洗扑克牌 │ ├── Interval.php 抽奖区间算法 │ ├── Maze.php 迷宫寻址算法 │ ├── AntsClimb.php 蚂蚁爬杆算法 │ ├── Encryption.php 对称加密算法 │ ├── ElevatorDispatch.php 编程之美-电梯调度算法 │ ├── PointInTriangle.php 向量叉集计算点是否在三角形中 │ ├── TraversalOfBinary.php 二叉树非递归遍历算法实现 │ ├── Knapsack.php 贪心算法之背包问实现 │ └── BigSmallReplace.php Hello World 输出 Olleh Dlrow │ └── Solution.php Facebook面试之岛屿周长算法 │ └── RotationSort.php Facebook面试之顺时针回旋算法 │ └── Square.php Facebook面试之判断四个点能否组成正方形算法 │ └── Prim.php Prim算法(最小生成树算法) │ └── CartesianProduct.php 笛卡尔积算法 │ └── Square.php 面试之平面任意四点能否组成一个矩形 │ └── Judge.php 面试之扑克牌中任选五张判断是不是顺子 │ └── Factorial.php 面试之N的阶乘末尾有多少个0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦里逆天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值