我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【链表问题】环形单链表约瑟夫问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【链表问题】环形单链表约瑟夫问题

前言

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

【题目描述】

【链表问题】环形单链表约瑟夫问题

【要求】

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

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

【难度】

士:★☆☆☆

【解答】

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

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

代码如下

 1    //时间复杂度为O(n*m)的解决方法
2    public static Node josephusKill(Node head, int m) {
3        if(head == null || m < 1)
4            return head;
5        Node last = head;
6        //定位到最后一个节点
7        while (head.next != last) {
8            head = head.next;
9        }
10        int count = 0;
11        while (head.next != head) {
12            if (++count == m) {
13                head.next = head.next.next;
14                count = 0;
15            } else {
16                head = head.next;
17            }
18        }
19        return head;
20    }

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

【链表问题】环形单链表约瑟夫问题

这个方法的时间复杂度为 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.所以我们可以采用递归的方式来做。

代码如下:

 1   //时间复杂度为O(n)
2    public static Node josephusKill2(Node head, int m) {
3        if(head == null || m < 1)
4            return head;
5        int n = 1;//统计一共有多少个节点
6        Node last = head;
7        while (last.next != head) {
8            n++;
9            last = last.next;
10        }
11        //直接用递归算出目的编号
12        int des = f(n, m);
13        //把目的节点取出来
14        while (--des != 0) {
15            head = head.next;
16        }
17        head.next = head;
18        return head;
19    }
20
21    private static int f(int n, int m) {
22        if (n == 1) {
23            return 1;
24        }
25        return (f(n - 1, m) + m - 1) % n + 1;
26    }

图片代码:

【链表问题】环形单链表约瑟夫问题

问题拓展

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【链表问题】环形单链表约瑟夫问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

【链表问题】环形单链表约瑟夫问题

前言以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获。每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢【题目描述】【要求】输入:一个环形单向链表的头节点 head 和报数 m.返回:最后
2023-06-02

C++约瑟夫环问题怎么实现

本文小编为大家详细介绍“C++约瑟夫环问题怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++约瑟夫环问题怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。题目如下:有一家公司,这个公司有一位老板和
2023-06-26

PHP怎么解决约瑟夫环问题

这篇文章主要讲解了“PHP怎么解决约瑟夫环问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP怎么解决约瑟夫环问题”吧!约瑟夫环问题(猴子选大王)PHP版约瑟夫斯问题问题有时候也被描述成
2023-06-22

Python实现约瑟夫环问题的方法

本文实例讲述了Python实现约瑟夫环问题的方法。分享给大家供大家参考,具体如下: 题目:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。 定义函数f(n,m),表
2022-06-04

C语言数据结构中约瑟夫环问题探究

这篇文章主要介绍了C语言数据结构中约瑟夫环问题,总的来说这并不是一道难题,那为什么要拿出这道题介绍?拿出这道题真正想要传达的是解题的思路,以及不断优化探寻最优解的过程。希望通过这道题能给你带来一种解题优化的思路
2023-01-12

C语言数据结构中约瑟夫环问题如何解决

本文小编为大家详细介绍“C语言数据结构中约瑟夫环问题如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言数据结构中约瑟夫环问题如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。问题描述约瑟夫环问题的
2023-07-04

Java之单链表问题的示例分析

这篇文章给大家分享的是有关Java之单链表问题的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。单链表单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表
2023-06-20

java基于双向环形链表解决丢手帕问题的示例分析

这篇文章主要为大家展示了“java基于双向环形链表解决丢手帕问题的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java基于双向环形链表解决丢手帕问题的示例分析”这篇文章吧。具体如下:问
2023-05-30

Golang中逆转链表问题怎么解决

今天小编给大家分享一下Golang中逆转链表问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Golang是一种基于
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录