闲来无事,看到园子里的一篇文章约瑟夫环问题的 PHP 实现--使用 PHP 数组内部指针操作函数,以前没有搞过,也没有听说什么什么环的,所以突然也想搞一下试试

问题大概这样子:一群猴子排成一圈,按 1,2,...,n 依次编号。然后从第 1 只开始数,数到第 m 只,把它踢出圈,从它后面再开始数, 再数到第 m 只,在把它踢出去...,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入 m、n, 输出最后那个大王的编号。

脑子比较直,所以第一个想法就是这n只首尾相接排成环状的猴子,不就是一个环状链表吗? 用C的话,马上就是这个概念了。但是PHP里面没有这东西,也不能定义结构体,如果用类来实现,实际上开销有点大好像。剩下来现成点的就是数组了,虽然php中的数组实际上就是哈希表,开销也远大于C中的数组,不过,能想到的就是这家伙了。

原来的兄弟是用prev,next等函数来操作,但是顾名思义,prev、next每次它只能前进一步、后退一步,这样实际上就无法避免要使用循环,例如往后6个,就要运行6次的next,所以,在性能上是不划算的。很抱歉,我是用虚拟主机用惯的人,太过计较一点性能上的浪费,没办法,苦日子过惯了,见不得奢侈。

先申明一点,我并没有任何别的意思,原来的兄弟也说了只是想实现下并未注重算法性能。

换一个角度看,假设说现在圈里面有5个人,我们要数12个,那么我们真的要一个一个去数,数6下?不要吧,相信大家都知道只要数2个,因为其中的10次实际上就是对圈里的5人数了2圈,在这期间,没有人会被踢出去,换句话说,这10次就是白数的。真正决定的,是后面的2次,所以,换一个方法如下:

function getKingMonkey1($n,$m)
{$a=range(1,$n); //声明一个包含n个元素的数组$c=$n;  //记录当前圈子中的人数$t=0;    //开始数数的位置while($c>1)  //圈中剩一个就结束{$t=$m%$c+$t;if($t>$c) $t=$t%$c;$t=$t>0?--$t:0;array_splice($a,$t,1);  //将不幸的兄弟踢出去--$c;   //圈中人数减一if($t==0) $t=$c;}return reset($a);
}

这个是原来的兄弟写的

//转自http://www.cnblogs.com/catprayer/archive/2010/10/04/1842085.htmlfunction getKingMonkey($n, $m)
{ $a = array();//声明内部数组 for($i = 1; $i <= $n; $i ++) { $a[$i] = $i;//这一步是对号入座 } reset($a);//为了严谨,我们来一个 reset() 函数,其实也可以省去 while(count($a) > 1)//主循环开始,这里使用的判别条件是数组元素的个数等于 1 的时候停止循环 { for($counter = 1; $counter <= $m; $counter++)//嵌套的 for 循环,用来“踢出”数到 m 的猴子 { if(next($a)){//如果存在 next 元素 if($counter == $m) { unset($a[array_search(prev($a), $a)]);//当数到 m 时,使用 unset() 删除数组元素 } } else//如果不存在 next 元素 { reset($a);//则数组的第一个元素充当 next 元素 if($counter == $m) { unset($a[array_search(end($a), $a)]);//当数到 m 时,使用 unset() 删除数组元素,注意这里是 end() reset($a);//记得让数组内部指针“归位” } } } } return current($a);
}

一、首先,用for循环为数组赋连续的值,是不划算的,用内置的range函数,就可以实现。

二、尽量避免多次调用count来获取数组数量,php中获取数组数量的方法和c#中不同,不如其高效,多次使用时,请使用局部变量来记录

三、在逻辑结构允许的情况下,++$t远比$t--来的合算,因为这点上,php是特殊的,像$t++,$t--这类的结构,它内部实际上多使用了一个局部变量来记录原值,所以,要多执行一个opcode

四、至于为什么踢出去的时候,使用array_splice而不用unset呢? 虽然unset属于语法结构,速度远比array_splice这种函数调用来的快,也都是可以将数组中的一个元素移除,但是,他们还是有不同之处。array_splice在移除数组的同时,会更改其后面索引类型为数字的元素的索引,而unset则不会。如

$a=array(0,1,'a'=>4,2,3,4,5,6);
array_splice($a,1,1);则结构就由原来的
array0 => int 01 => int 1'a' => int 42 => int 23 => int 34 => int 45 => int 56 => int 6
变为:
array0 => int 0'a' => int 41 => int 22 => int 33 => int 44 => int 55 => int 6

换句话说,就是array_splice在移除元素之后,会对索引做一个重排,所以,在不影响使用的情况下,尽量使用unset来取代array_splice,即使是一次需要移除多个元素的情况。我这里要它重排下,所以只能依了它。

最终,运行的结果如下

在10人中数6人的情况

在人数及数人的数量增多的情况下,循环带来的开销会更明显,例如100人数81

也是过苦日子的兄弟,可以参考 优化php代码的40条建议

转载于:https://www.cnblogs.com/xin478/archive/2010/10/18/1852346.html

无聊闲做,从使用PHP数组实现约瑟夫环问题谈性能相关推荐

  1. C#数组解决约瑟夫环问题

    using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace 约瑟夫环 ...

  2. 约瑟夫环(循环数组循环链表)

    目录 1.循环数组 2.循环链表 题目 1 .一群猴子要选新猴王.新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号.从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子, ...

  3. Window 消息大全使用详解(无聊没事做)

    Window 消息大全使用详解(无聊没事做) 楼主zhangqu_980371(能坚持一辈子的东西太少)2004-12-19 16:35:23 在 VC/MFC / 基础类 提问     消息,就是指 ...

  4. Bootstrap制作虚拟系统初始版本(无聊随便做的)

    Bootstrap制作虚拟系统初始版本(无聊随便做的) 距离我上次发博客已经有了很久了,这次纯属无聊来更新下.PS:(这个前端程序花了我2小时才写完) 废话不多说,直接上代码. 主系统 <!do ...

  5. C语言用数组1. 简单约瑟夫环问题: N个人,编号从1~N围成一圈,输入一个数T,从1号开始报数,报到T的人出圈;下一人又从1开始报数,下一个报到T的人出圈,输出出圈顺序。 考虑问实现约瑟夫环问题

    1. 简单约瑟夫环问题: N个人,编号从1~N围成一圈,输入一个数T,从1号开始报数,报到T的人出圈:下一人又从1开始报数,下一个报到T的人出圈,输出出圈顺序. 考虑问题: 报到T的人出圈,怎么表示出 ...

  6. LeetCode 937. 重新排列日志文件 / 1823. 找出游戏的获胜者(约瑟夫环问题) / 713. 乘积小于 K 的子数组

    937. 重新排列日志文件 2022.5.3 每日一题 题目描述 给你一个日志数组 logs.每条日志都是以空格分隔的字串,其第一个字为字母与数字混合的 标识符 . 有两种不同类型的日志: 字母日志: ...

  7. 约瑟夫环---自杀环问题 C++数组实现 数学推理

    约瑟夫环–自杀环问题 约瑟夫环问题有着这样的历史: Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓.于是决定了自杀方式,41个 ...

  8. OJ.2324: 约瑟夫环问题【数组】

    2324: 约瑟夫环问题[数组] Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 714   Solved: 402 [ Submit][ Statu ...

  9. 约瑟夫环-(数组、循环链表、数学)

    约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出 ...

最新文章

  1. java中用于选择按钮的语句_java程序员考试套题1
  2. APP市场火热的背后 云计算技术不是核心竞争力
  3. 中文分词_中文分词最佳纪录刷新,两大模型分别解决中文分词及词性标注问题...
  4. P1031 均分纸牌(经典贪心)
  5. mysql 多数据库事务_多数据库事务处理
  6. 深度学习修炼(五)——基于pytorch神经网络模型进行气温预测
  7. cefsharp 加载网页慢_网站访问慢的排查方案(史上最详细)
  8. S5PV210裸机之时钟
  9. 项目基于vue-uniapp,使用colorUi与uview框架,完美支持微信小程序
  10. java的继承关系linkedlist_LinkedList——JAVA成长之路
  11. 【编程练习】复习一下树的遍历
  12. 中国内容推荐引擎市场趋势报告、技术动态创新及市场预测
  13. YOLO 检测算法分析
  14. 2022年计算机二级Java语言程序设计练习题及答案
  15. 工业3D互联网可视化三维数字化智能工厂管理系统
  16. 基于Python的电影数据可视化分析系统 设计报告+答辩PPT+项目源码
  17. Summer School实验
  18. qlv文件是什么?qlv文件格式介绍
  19. android 批量安装apk,如何一键批量安装APP应用apk安装包?
  20. 修改MySQL数据库密码的多种方法

热门文章

  1. 解封装(七):av_read_frame读取帧数据函数分析和产生的空间问题分析,以及AVPacket分析
  2. redis的hash类型
  3. python中msg是什么意思,使用python解析Outlook .msg文件
  4. redis 缓存目标
  5. jinja Evnironment
  6. 11 User Space, Kernel Space, and the System Call API(用户空间,核空间,系统api)
  7. C语言 FileStreaming(文件流)
  8. opencv-api cvtColor
  9. flask.Blueprint
  10. python 格式化输出