题目描述

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

牛客网刷题地址

思路分析

  1. 采用链表来存放数据,每次对长度取余来实现循环:

    • 将所有数字放入LinkedList链表中(LinkedList比ArrayList更适合增删操作)。假设当前删除的结点下标为removeIndex,则下一个要删除的结点的下标为:(removeIndex+m-1)%list.size(),通过取余符号可以实现类型循环的操作
    • 注:没必要用循环链表,反而会更麻烦了。
  2. 数学推导规律
      n个数字的圆圈,不断删除第m个数字,我们把最后剩下的数字记为f(n,m)
      n个数字中第一个被删除的数字是(m-1)%n, 我们记作k,k=(m-1)%n
      那么剩下的n-1个数字就变成了:0,1,……k-1,k+1,……,n-1,我们把下一轮第一个数字排在最前面,并且将这个长度为n-1的数组映射到0~n-2。
      原始数字:k+1,……, n-1,0, 1,……k-1
      映射数字:0,……,n-k-2, n-k-1, n-k,……n-2
      把映射数字记为x,原始数字记为y,那么映射数字变回原始数字的公式为 y=(x+k+1)%n。
      在映射数字中,n-1个数字,不断删除第m个数字,由定义可以知道,最后剩下的数字为f(n-1,m)。我们把它变回原始数字,由上一个公式可以得到最后剩下的原始数字是(f(n-1,m)+k+1)%n,而这个数字就是也就是一开始我们标记为的f(n,m),所以可以推得递归公式如下:
              f(n,m) =(f(n-1,m)+k+1)%n       
      将k=(m-1)%n代入,化简得到:
              f(n,m) =(f(n-1,m)+m)%n
              f(1,m) = 0
      代码中可以采用循环或者递归的方法实现该递归公式。时间复杂度为O(n),空间复杂度为O(1)。

测试用例

  1. 功能测试:输入的m小于n,比如从最初有5个数字的圆圈中每次删除第2、3个数字;输入的m大于或者等于n,比如从最初有6个数字的圆圈中每次删除第6、7个数字。
  2. 特殊输入测试:圆圈中有0个数字。
  3. 性能测试:从最初有4000个数字的圆圈中每次删除第997个数字。

Java代码

public class Offer062 {
public static void main(String[] args) {
test1();
test2();
test3(); } public static int LastRemaining(int n, int m) {
return Solution1(n, m);
} /*
* 方法一:采用推导出来的方法
*/
public static int Solution1(int n, int m) {
if(n<1 || m<1)
return -1; //出错
int last=0;
for(int i=2;i<=n;i++){
last=(last+m)% i; //这里是i不是n!!!
}
return last;
} /*
* 方法二:采用链表来存放,每次对长度取余来实现循环
*/
public static int Solution2(int n, int m) {
if(n<1 || m<1)
return -1; //出错
LinkedList<Integer> list = new LinkedList<Integer>();
for(int i=0;i<n;i++)
list.add(i);
int removeIndex=0;
while(list.size()>1){
removeIndex=(removeIndex+m-1)%list.size();
list.remove(removeIndex);
}
return list.getFirst();
} private static void test1() { } private static void test2() { }
private static void test3() { } }

代码链接

剑指Offer代码-Java

【Offer】[62] 【圆圈中最后剩下的数字】的更多相关文章

  1. 剑指 Offer 62. 圆圈中最后剩下的数字 + 约瑟夫环问题

    剑指 Offer 62. 圆圈中最后剩下的数字 Offer_62 题目描述 方法一:使用链表模拟 这种方法是暴力方法,时间复杂度为O(nm),在本题中数据量过大会超时. 方法二:递归方法 packag ...

  2. [剑指offer]62.圆圈中最后剩下的数字

    62.圆圈中最后剩下的数字 题目 0,1,...,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成 ...

  3. 【Java】 剑指offer(62) 圆圈中最后剩下的数字

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每 ...

  4. Java实现 LeetCode 面试题62. 圆圈中最后剩下的数字(约瑟夫环)

    面试题62. 圆圈中最后剩下的数字 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成一个圆 ...

  5. 【LeetCode】面试题62. 圆圈中最后剩下的数字

    题目:面试题62. 圆圈中最后剩下的数字 这题很有意思,也很巧妙,故记录下来. 官方题解思路,是约瑟夫环的数学解法: 我们将上述问题建模为函数 f(n, m),该函数的返回值为最终留下的元素的序号. ...

  6. 《剑指offer》面试题62. 圆圈中最后剩下的数字

    问题描述 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成一个圆圈,从数字0开始每次删除第 ...

  7. [LeetCode]面试题62. 圆圈中最后剩下的数字(数学)

    题目 0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成一个圆圈,从数字0开始每次删除第3 ...

  8. 【LeetCode】面试题62. 圆圈中最后剩下的数字 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 约瑟夫环 日期 题目地址:https://leetco ...

  9. 剑指offer——72圆圈中最后剩下的数字

    题目描述 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...

  10. 【剑指offer】圆圈中最后剩下的数字(约瑟夫问题),C++实现

    原创博文,转载请注明出处! # 题目 # 思路 本题即为典型的约瑟夫问题,通过递推公式倒推出问题的解.原始问题是从n个人中每隔m个数踢出一个人,原始问题变成从n-1个人中每隔m个数踢出一个人--    ...

随机推荐

  1. idea使用大全(加载mysql驱动)

    1.载入mysql驱动 找到项目结构(project structure) 选Modules 找到右边的加号选择第一个 OK

  2. mysql优化---订单查询优化(1):视图优化+索引创建

    订单的表结构采用了垂直分表的策略,将订单相关的不同模块的字段维护在不同表中 在订单处理这个页面,需要查询各种维度, 因此为了方便查询创建了v_sale_order视图(老版本) drop view v ...

  3. c# 多进程写信息到前台控件

    private void DispMsg(string strMsg, bool clearlb = false) { if (this.lberror.InvokeRequired == false ...

  4. 洛谷 P2657 [SCOI2009]windy数

    题意简述 求l~r之间不含前导零且相邻两个数字之差至少为2的正整数的个数 题解思路 数位DP 代码 #include <cstdio> #include <cstring> # ...

  5. MongoDB Day 1

    创建数据库 db.createCollection("user"); 插入字段 //----insert------- db.user.insert({uid:1, user_co ...

  6. Okhttp3源码解析(1)-OkHttpClient分析

    ### 前言 上篇文章我们讲了[Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f),今天根据上节讲到请求流程来分析源码,那么第一步就是实例化OkH ...

  7. linux_密钥

    使用密钥文件.       这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件.   在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...

  8. java 路径问题

    java路径存在两种写法"/"和"\\" String path="D:\\1.txt"; String path1="D:/1. ...

  9. Vue仿微信app页面跳转动画

    10:14:11独立开发者在开发移动端产品时,为了更高效,通常会使用Web技术来开发移动端项目,可以同时适配Android.iOS.H5,稍加改动还可适配微信小程序. 在使用Vue.js开发移动端页面 ...

  10. Linux 用户和组 权限管理 常用命令与参数

    ========================================================================== 1.基本概念: 所有者 : 一般为文件的创建者,谁 ...