面试问到约瑟夫环问题,三种方法拿捏了!

约瑟夫环问题

前言

大家好,我是bigsai!

约瑟夫环问题是算法中相当经典的一个问题,其问题理解是相当容易的,并且问题描述有非常多的版本,并且约瑟夫环问题还有很多变形,这篇约瑟夫问题的讲解,一定可以带你理解通通!

什么是约瑟夫环问题?

约瑟夫环问题在不同平台被"优化"描述的不一样,例如在牛客剑指offer叫孩子们的游戏,还有叫杀人游戏,点名……最直接的感觉还是力扣上剑指offer62的描述:圆圈中最后剩下的数字

问题描述:

0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

当然,这里考虑m,n都是正常的数据范围,其中

  • 1 <= n <= 10^5
  • 1 <= m <= 10^6

对于这个问题,你可能脑海中有了印象,想着小时候村里一群孩子坐在一起,从某个开始报数然后数到几出列,下一个重新开始一直到最后一个。

循环链表模拟

这个问题最本质其实就是循环链表的问题,围成一个圈之后,就没有结尾这就是一个典型的循环链表嘛!一个一个顺序报数,那不就是链表的遍历枚举嘛!数到对应数字的出列,这不就是循环链表的删除嘛!

链表模拟

并且这里还有非常方便的地方:

  • 循环链表的向下枚举不需要考虑头尾问题,直接node=node.next向下
  • 循环聊表的删除也不需要考虑头尾问题,直接node.next=node.next.next删除

当然也有一些需要注意的地方

  • 形成环形链表很简单,只需要将普通链表的最后一个节点的next指向第一个节点即可

  • 循环链表中只有一个节点的时候停止返回,即node.next=node的时候

  • 删除,需要找到待删除的前面节点,所以我们删除计数的时候要少即一位,利用前面的那个节点直接删除后面节点即可

这样,思路明确,直接开撸代码:

class Solution {
    class node//链表节点
    {
        int val;
        public node(int value) {
            this.val=value;
        }
        node next;
    }
    public int lastRemaining(int n, int m) {
        if(m==1)return n-1;//一次一个直接返回最后一个即可
        node head=new node(0);
        node team=head;//创建一个链表
        for(int i=1;i<n;i++)
        {
            team.next=new node(i);
            team=team.next;
        }
        team.next=head;//使形成环
        int index=0;//从0开始计数
        while (head.next!=head) {//当剩余节点不止一个的时候
            //如果index=m-2 那就说明下个节点(m-1)该删除了
            if(index==m-2)
            {
                head.next=head.next.next;
                index=0;
            }
            else {
                index++;
            }
            head=head.next;
        }
        return head.val;
    }
}

当然,这种算法太复杂了,大部分的OJ你提交上去是无法AC的,因为超时太严重了,具体的我们可以下面分析。

有序集合模拟

上面使用链表直接模拟游戏过程会造成非常严重非常严重的超时,n个数字,数到第m个出列。因为m如果非常大远远大于m,那么将进行很多次转圈圈。

所以我们可以利用的方法判断等价最低的枚举次数,然

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

图解数据结构与算法(Java) 文章被收录于专栏

让数据结构与算法学习更简单,每一种数据结构与算法通过多图的方式讲解、实现、解题,内容覆盖递归详解、单双链表、堆、栈、二叉树(遍历、插删)、AVL树、哈夫曼树、字典树、dfs、bfs、拓扑排序、Dijkstra、Floyd、并查集、跳表、分治算法、动态规划、快速幂、十大排序等等。 还覆盖超经典面试笔试题例如:topK问题、约瑟夫环问题、链表找环问题、LRU、20+道经典动态规划问题!

全部评论
楼主厉害啊,佩服
点赞 回复 分享
发布于 2022-06-11 20:56

相关推荐

04-08 21:41
南京大学 Java
先整理一下时间线吧:&nbsp;&nbsp;&nbsp;&nbsp;3.27一面&nbsp;&nbsp;&nbsp;&nbsp;4.2二面&nbsp;&nbsp;&nbsp;&nbsp;4.7晚上hr打电话oc&nbsp;&nbsp;&nbsp;&nbsp;4.8发的offer得说不知道为啥我这个美团的流程走的好慢,我朋友和我前后脚第一次一面,我走了一遍流程拿的offer,他走了两编流程跟我同一天拿的offer,搞得我中间以为二面直接寄了。---------------------------------------------------------------------------------------------------一面上来自我介绍之后面试官对我大模型的论文特别感兴趣,上来让我说一下前端实习的项目以后一句没问,直接让开讲大模型实验是怎么做的,然后让我给他展示我论文里的prompt是怎么写的。之后出了一道需求让我手搓prompt给大模型试试生成的代码的质量。最后出了个人机交互的题目,分析一下用户对系统的三个反馈问题哪个问题最要紧,三个问题修正的顺序怎么安排。全程大概60分钟整,一道前端八股没问,给我整懵逼了。二面二面同理,感觉美团面试官对大模型特别感兴趣,上来也让我讲论文实验思路,完了讲讲对实验设计有没有更好的优化的想法,我说准备做个根据大模型生成结果的得分做个multi-query的操作提高性能(被批说大概率没用)。之后开始问我怎么保证一个项目进展的顺利,我说在项目开展之前对任务量进行评估,计算每周要做多少,设立里程碑,每周结束的时候做评估。然后开始让结合实习经历讲讲怎么保证项目里各个角色合作顺利开展,比如前端怎么和后端argue系统设计啥的。之后开始让讲怎么学习一个新技术,以及对大模型有什么看法,觉得大模型对个人和学校有什么影响。(也是一道八股没问)无hr面,二面面完直接给我oc,第二天发的offer。(美团offer发的太快了,后面淘天约我三面我直接拒了,实在不想面试了,太累了,之前阿里控股给我连挂四次)#美团##我的OC时间线##晒一晒我的offer#
点赞 评论 收藏
分享
04-10 12:19
已编辑
西安电子科技大学 Java
#牛客AI配图神器#核心本地商业-基础研发平台面试官简单介绍了一下业务,问我会不会c++(人晕了)20分钟项目1.实习阶段的一些收获,技术上,方法上都可以2.读文件格式怎么判断3.如果给的文件本身就很大,那怎么读取基础问题&nbsp;(30分钟)1.并发和并行2.进程间通信的方式3.我们在使用过程中该怎么选用哪种通信方式4.如果我们消息有容量的要求呢5.如果对速度有要求呢6.http常见响应状态码7.为什么要编这么多状态码8.如果没有状态码会有什么问题没有码怎么判断成功失败,为什么失败会有这么多呢9.这么多的错误码作用是什么10.get和post请求的区别11.本质上的做法有哪里不同,适用什么场景12.执行效率方面有什么区别(get&nbsp;post的header是分开还是合并,这些方面会影响http的交互方式)13.c++:&nbsp;虚函数&nbsp;(寄)14.java&nbsp;:break&nbsp;continue&nbsp;return&nbsp;怎么用的15.如果定义一个局部变量:private&nbsp;static&nbsp;final&nbsp;int&nbsp;size&nbsp;=&nbsp;100,每个关键字的含义是什么16.java集合体系介绍一下17.数据库:&nbsp;三范式,不用硬套答案名词,设计数据库字段表的规范和经验讲一讲18.sql是什么含义19.结构化怎么体现20.linux:&nbsp;看文件内容怎么操作21.找一个占用空间最大的文件该怎么做手撕:hot100&nbsp;在排序数组中查找元素的第一个和最后一个位置&nbsp;的&nbsp;变式在本地ide做的,撕完了讲解了下思路反问=============================不同于常规八股,会深入问自己的理解,面试官人很好,会引导着思考问题,许愿二面
查看25道真题和解析
点赞 评论 收藏
分享
评论
9
21
分享

创作者周榜

更多
牛客网
牛客企业服务