前言

以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获。每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢

【题目描述】

【要求】

输入:一个环形单向链表的头节点 head 和报数 m.

返回:最后生存下来的节点,且这个节点自己组成环形单向链表,其他节点都删除掉。

【难度】

士:★☆☆☆

【解答】

方法1:时间复杂度为 O( n * m)

这道题如果不考虑时间复杂度的话还是挺简单的,就遍历环形链表,每遍历 m 个节点就删除一个节点,知道链表只剩下一个节点就可以了。

代码如下//时间复杂度为O(n*m)的解决方法

public static Node josephusKill(Node head, int m){

if(head == null || m

return head;

//定位到最后一个节点

while (head.next != last) {

int count = 0;

while (head.next != head) {

if (++count == m) {

0;

else {

return head;

由于有些手机可能会出现乱码问题,我这里再贴出图片:

这个方法的时间复杂度为 O(n * m)。下面用时间复杂度为方法解决。

方法二:时间复杂度为 O(n)

这个方法的难度为:

校:★★★☆

我们可以给环形链表的节点编号,如果链表的节点数为 n, 则从头节点开始,依次给节点编号,即头节点为 1, 下一个节点为2, 最后一个节点为 n.

我们用 f(n) 表示当环形链表的长度为n时,生存下来的人的编号为 f(n),显然当 n = 1 时,f(n) = 1。假如我们能够找出 f(n) 和 f(n-1) 之间的关系的话,我们我们就可以用递归的方式来解决了。我们假设 人员数为 n, 报数到 m 的人就自杀。则刚开始的编号为

m - 2

m - 1

m

m + 1

m + 2

进行了一次删除之后,删除了编号为m的节点。删除之后,就只剩下 n - 1 个节点了,删除前和删除之后的编号转换关系为:

删除前     ---     删除后

… --- …

m - 2     ---     n - 2

m - 1    ---      n - 1

m         ----    无(因为编号被删除了)

m + 1     ---     1(因为下次就从这里报数了)

m + 2     ----     2

…         ----         …

新的环中只有 n - 1 个节点。且编号为 m + 1, m + 2, m + 3 的节点成了新环中编号为 1, 2, 3 的节点。

假设 old 为删除之前的节点编号, new 为删除了一个节点之后的编号,则 old 与 new 之间的关系为 old = (new + m - 1) % n + 1。注:有些人可能会疑惑为什么不是 old = (new + m ) % n 呢?主要是因为编号是从 1 开始的,而不是从 0 开始的。如果 new + m == n的话,会导致最后的计算结果为 old = 0。所以 old = (new + m - 1) % n + 1.

这样,我们就得出 f(n) 与 f(n - 1)之间的关系了,而 f(1) = 1.所以我们可以采用递归的方式来做。

代码如下://时间复杂度为O(n)

public static Node josephusKill2(Node head, int m){

if(head == null || m

return head;

int n = 1;//统计一共有多少个节点

while (last.next != head) {

//直接用递归算出目的编号

int des = f(n, m);

//把目的节点取出来

while (--des != 0) {

return head;

private static int f(int n, int m){

if (n == 1) {

return 1;

return (f(n - 1, m) + m - 1) % n + 1;

图片代码:

问题拓展

对于上道题,假设是从第 K 个节点开始报数删除呢? 又该如何解决呢?

java 约瑟夫问题 链表_【链表问题】环形单链表约瑟夫问题相关推荐

  1. python线性链表_线性表 (单链表、循环链表-python实现)

    #定义每个节点 classNode:def __init__(self,data): self.data=data self.next=NoneclasslinkList:#初始化头结点 def __ ...

  2. 左神算法:环形单链表的约瑟夫问题(Java版)

    本题来自左神<程序员面试代码指南>"环形单链表的约瑟夫问题"题目. 题目 据说,著名犹太历史学家 Josephus 有过以下故事: 在罗马人占领乔塔帕特后,39 个犹太 ...

  3. 构造数组MaxTree、环形单链表的约瑟夫问题等总结

    1.构造数组的MaxTree 定义二叉树节点如下: public class Node{ public int value; public Node left; public Node right; ...

  4. 环形单链表的约瑟夫问题

    输入:一个环形单链表的头结点head和报数的值m. 返回:最后生存下来的节点,且这个节点自己组成环形单向链表,其他节点都删掉. 进阶:如果链表节点数为N,想在时间复杂度O(N)时完成原问题的要求,该如 ...

  5. 链表问题18——向有序的环形单链表中插入新节点

    题目 一个环形链表从头节点开始的顺序为不降序的顺序,也就是如1->2->2->2->3->4这样的链表叫做不降序,同时由最后的节点指回头节点.给定这个环形单链表的头节点h ...

  6. Coding Interview Guide -- 向有序的环形单链表中插入新节点

    [题目] 一个环形单链表从头节点head开始不降序,同时由最后的节点指回头节点.给定这样一个环形单链表的头节点head和一个整数num,请生成节点值为num的新节点,并插入到这个环形链表中,保证调整后 ...

  7. 单链表的合并算法_图解算法:单链表两两反转 | 眼睛会了手就会系列

    一. 序 链表作为一种基本的数据结构,本身理解起来,很简单.它通过指针或者叫引用,将一组零散的内存空间(结点),串联起来组成一个数据存储结构. 链表根据其指针的指向和丰富程度,可以分为单链表.双向链表 ...

  8. 链表的基本操作 java_JAVA实现单链表的基本操作

    复习单链表的实现,扎实基础,单链表的结构不在赘述,直接看代码,注释的很清楚 注意:在插入和删除操作时,需要判断是否越界,如何判断上界?想到了在修改. public class linkList { / ...

  9. 带头结点单链表 和 不带头结点单链表的区别

    文章目录 不带头结点的操作 代码① 代码② 代码③ 代码④ 带头结点的操作 代码⑤ 下面的代码中,传递链表时,传的是头指针.如果是带头结点的链表,传递链表时,可以传头结点,具体可以看看 C语言实现-线 ...

最新文章

  1. 收藏!一篇文章搞懂项目管理
  2. linux删除旧网卡,如何删除旧网卡驱动
  3. mysql导入sas文件夹_MYSQL导出HTML格式数据如何导入到SAS中
  4. 写给找工作的朋友——最典的面试葵花宝典
  5. ASP.NET Core Web API 集成测试中使用 Bearer Token
  6. laravel -admin 禁止某一行删除
  7. 343. 整数拆分(JavaScript)
  8. matlab 计算指北角,用MATLAB如何计算出矩形区域内的最大值?
  9. Kernel Method核方法—应用与理解
  10. iOS应用不同状态下收到推送的处理
  11. Java-在线聊天系统-线程
  12. Android—构建安全的Android客户端请求,避免非法请求
  13. html5文字布局排版欣赏,用文字作为主体排版的15个网页设计案例
  14. Collection、List、泛型、数据结构
  15. 零中频接收机频率转换图_德国Ramp;S罗德与施瓦茨EMI测试接收机ESR系列
  16. python 多态app_**python多态
  17. 《多媒体技术基础》辅导
  18. 洛谷 P1564 膜拜 C++ dp
  19. 实验08 路由器RIP动态路由配置实验报告
  20. Linux安装Nginx 作者:哇塞大嘴好帅

热门文章

  1. 怎样在VirtualBox 虚拟机中挂载共享目录
  2. SQL字符串基本操作汇总
  3. 设置IP安全策略将***阻杀在端口外
  4. 比特币分叉两年记:聊聊当年为什么要分叉?
  5. Robinhood应用宣布添加BCH和LTC交易
  6. Electron Cash发布功能机BCH钱包,低端市场利好来袭
  7. px、em、rem、vw、vh、vm、rpx这些单位的
  8. 20165206 2017-2018-2 《Java程序设计》第三周学习总结
  9. java 调 pro*c
  10. 师生对话:我们都曾是爱学习的孩子