本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目

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

思路

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

  将所有数字放入LinkedList链表中(LinkedList比ArrayList更适合增删操作)。假设当前删除的结点下标为removeIndex,则下一个要删除的结点的下标为:(removeIndex+m-1)%list.size(),通过取余符号可以实现类型循环的操作。

  注:没必要用循环链表,反而会更麻烦了。

  方法二:数学推导规律

  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)

  2.特殊测试(n、m<=0)

  3.性能测试(n=4000,n=997)

Java代码

//题目:0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里
//删除第m个数字。求出这个圆圈里剩下的最后一个数字。 public class LastNumberInCircle {
/*
* 方法一:采用推导出来的方法
*/
public int LastRemaining_Solution(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 int LastRemaining_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();
}
}

  

收获

  1.对于下标循环一圈类似的问题,通过%可以很好地实现循环,而不需要我们自己构造循环链表;

  2.(a%n+b)%n=(a+b)%n

  3.尽量学会本题的数学方法,特别是要掌握好数字间映射的方法。

  4.公式法中,last=(last+m)% i;  //这里是i不是n!!!

 

更多:《剑指Offer》Java实现合集  

【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. 【剑指offer】圆圈中最后剩下的数字(约瑟夫问题),C++实现

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

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

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

  5. 剑指offer46:圆圈中最后剩下的数字(链表,递归)

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

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

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

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

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

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

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

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

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

随机推荐

  1. 网站程序CMS识别

    CMS cms一般有dedecms(织梦),dzcms,phpweb,phpwind,phpcms,ecshop,dvbbs,siteweaver,aspcms,帝国,zblog,wordpress等 ...

  2. android contentprovider内容提供者

    contentprovider内容提供者:让其他app可以访问私有数据库(文件) 1.AndroidManifest.xml 配置provider <?xml version="1.0 ...

  3. nxlog 日志采集

    Nxlog 主要用于各业务后端服务的日志采集,windows环境和linux环境都支持. RPM 包:rpm -ivh http://nxlog.co/system/files/products/fi ...

  4. JavaScript之HTML5 data-* 自定义属性[HTML5标准 node.dataset.attributeName]

    在HTML5中添加了data-*的方式来自定义属性,所谓data-*实际上上就是data-前缀加上自定义的属性名,使用这样的结构可以进行数据存放. 使用data-*可以解决自定义属性混乱无管理的现状. ...

  5. python(七) Python中单下划线和双下划线

    Python中单下划线和双下划线: 一.分类 (1).以单下划线开头,表示这是一个保护成员,只有类对象和子类对象自己能访问到这些变量. 以单下划线开头的变量和函数被默认是内部函数,使用from mod ...

  6. 数据库运维平台~inception回滚功能

    一 简介:inception的另一个激动人心的功能,很强大.二 功能简介: inception会针对已经执行sql语句进行1 记录 2 生成回滚语句三 备份:   1 启用远程备份机制(强烈建议一台单 ...

  7. Hadoop的RPC机制及简单实现

    1.RPC简介 Remote Procedure Call 远程过程调用协议 RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些 ...

  8. DataSnap ClientdataSet 三层中主从表的操作

    非原创  摘自:http://hi.baidu.com/yagzh2000/blog/item/fc69df2cb9845de78b139946.html三层中主从表的操作(删除.新增.修改)一定要在 ...

  9. Oracle数据库修改LISTENER的监听端口

    背景 这又是个不作不会死的事情,自己不懂,硬搞,端口换了,后来竟然捣鼓好了.尽量少搞这些事情. 注意点 http://wallimn.iteye.com/blog/1163614 修改配置文件后,需修 ...

  10. centos 6.5环境利用iscsi搭建SAN网络存储服务及服务端target和客户端initiator配置详解

    一.简介 iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够 ...