题目:

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

思路:

1、环形链表模拟圆圈

创建一个n个节点的环形链表,然后每次在这个链表中删除第m个节点;

可以用std::list来模拟环形链表,list本身不是环形结构,因此每当迭代器扫描到链表末尾的时候,需要将迭代器移到链表的头部。

2、分析每次被删除的数字的规律,动态规划

假设从0-n-1中删除了第m个数字,则下一轮的数字排列为m,m+1,.....n,1,2,3...m-2,将该数字排列重新映射为0~n-2,则为

m    0

m+1    1  

....    ....

n-1   n-1-m

0    n-m

1    n-m+1

...    ....

m-2    n-2

可以看出从右往左的映射关系为left=(right+m)%n,即0~n-1序列中最后剩下的数字等于(0~n-2序列中最后剩下的数字+m)%n,很明显当n=1时,只有一个数,那么剩下的数字就是0.

问题转化为动态规划问题,关系表示为:

f(n)=(f(n-1)+m)%n; 当n=1,f(1)=0;

代码:

1、环形链表

  1. #include <iostream>
  2. #include <list>
  3. using namespace std;
  4.  
  5. int lastRemaining(unsigned int n,unsigned int m){
  6. if(n<1 || m<1)
  7. return -1;
  8.  
  9. std::list<int> numbers;
  10. for(unsigned int i=0;i<n;i++)
  11. numbers.push_back(i);
  12.  
  13. std::list<int>::iterator current=numbers.begin();
  14. std::list<int>::iterator next;
  15. while(numbers.size()>1){
  16. for(unsigned int i=1;i<m;i++){
  17. current++;
  18. if(current==numbers.end())
  19. current=numbers.begin();
  20. }
  21. next=++current;
  22. if(next==numbers.end())
  23. next=numbers.begin();
  24.  
  25. --current;
  26. numbers.erase(current);
  27. current=next;
  28. }
  29. return *(current);
  30. }
  31.  
  32. int main()
  33. {
  34. cout << lastRemaining(5,3) << endl;
  35. return 0;
  36. }

2、映射规律,动态规划

  1. int lastRemaining_1(unsigned int n,unsigned int m){
  2. if(n<1 || m<1)
  3. return -1;
  4.  
  5. int last=0;
  6. for(int i=2;i<=n;i++){
  7. last=(last+m)%i;
  8. }
  9. return last;
  10. }
  11.  
  12. int lastRemaining_2(unsigned int n,unsigned int m){
  13. if(n<1 || m<1)
  14. return -1;
  15. if(n==1)
  16. return 0;
  17. return (lastRemaining_2(n-1,m)+m)%n;
  18. }

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/f78a359491e64a50bce2d89cff857eb6?rp=2

AC代码:

1、环形链表

  1. class Solution {
  2. public:
  3. int LastRemaining_Solution(unsigned int n, unsigned int m)
  4. {
  5. if(n<1 || m<1)
  6. return -1;
  7.  
  8. std::list<int> numbers;
  9. for(unsigned int i=0;i<n;i++)
  10. numbers.push_back(i);
  11.  
  12. std::list<int>::iterator current=numbers.begin();
  13. std::list<int>::iterator next;
  14.  
  15. while(numbers.size()>1){
  16. for(unsigned int i=1;i<m;i++){
  17. ++current;
  18. if(current==numbers.end())
  19. current=numbers.begin();
  20. }
  21.  
  22. next=++current;
  23. if(next==numbers.end())
  24. next=numbers.begin();
  25.  
  26. --current;
  27. numbers.erase(current);
  28. current=next;
  29. }
  30.  
  31. return *current;
  32. }
  33. };

2、序列规律,动态规划

  1. class Solution {
  2. public:
  3. int LastRemaining_Solution(unsigned int n, unsigned int m)
  4. {
  5. if(n<1 || m<1)
  6. return -1;
  7. int last=0;
  8. for(int i=2;i<=n;i++)
  9. last=(last+m)%i;
  10.  
  11. return last;
  12. }
  13. };
  1. class Solution {
  2. public:
  3. int LastRemaining_Solution(unsigned int n, unsigned int m)
  4. {
  5. if(n<1 || m<1)
  6. return -1;
  7. if(n==1)
  8. return 0;
  9.  
  10. return (LastRemaining_Solution(n-1,m)+m)%n;
  11. }
  12. };

(剑指Offer)面试题45:圆圈中最后剩下的数字的更多相关文章

  1. 【剑指Offer】孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python)

    [剑指Offer]孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-in ...

  2. 《剑指offer》面试题45 圆圈中最后剩下的数字(Java版本)

    引言 这道题网上的讲解都是直接抄书,没意思,所以想自己写一写,补充一下,便于自己理解.另外,大家都忽略了经典解法,虽然这种解法效率不及第二种,但是我觉得在项目当中阅读性其实很重要,牺牲一点点效率保证代 ...

  3. 【剑指Offer】46、圆圈中最后剩下的数

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

  4. 剑指Offer 46. 孩子们的游戏(圆圈中最后剩下的数) (其他)

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

  5. [剑指offer] 46. 孩子们的游戏(圆圈中最后剩下的数)

    题目描述 随机指定一个数m,让编号为0的小朋友开始报数.每次喊到m-1的那个小朋友要出列,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友 ...

  6. 【剑指offer】孩子们的游戏(圆圈中最后剩下的数)

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

  7. C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解

    剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...

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

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

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

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

  10. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

随机推荐

  1. .net C# 利用Session防重复点击防重复提交

    <body>    <form id="form1" runat="server">    <div>        < ...

  2. [leetcode]58. Length of Last Word最后一个词的长度

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  3. echart.js在vue中使用

    以前可能写过,懒得去翻了,再写一次 1,安装echarts   导入到页面 import echarts from 'echarts'; 2.在生命周期里面做初始化 data(){ return{ t ...

  4. Idea+maven+testNG+Selenium+ReportNG自动化框架搭建

    1.Idea创建一个空的Maven项目 创建后默认项目目录如图所示 2.配置pom.xml文件 <?xml version="1.0" encoding="UTF- ...

  5. Shell 脚本获取当前目录 和 获得 文件夹名

    #!/bin/bash project_path=$(cd ``; pwd) project_name="${project_path##*/}" echo $project_pa ...

  6. SSM三大框架整合

    三大框架整合的思路 1.Dao层: Mybatis的配置文件:SqlMapConfig.xml 不需要配置任何内容,需要有文件头.文件必须存在. applicationContext-dao.xml: ...

  7. SpringMVC Controller中注入Request成员域和在方法中定义中HttpServletRequest有啥区别

    先说结论,在Controller中注入Request是线程安全的. 以下是解释: 我们先来看看这两者有什么不同 在controller注入成员变量request 可以看到注入的是一个代理对象 写在方法 ...

  8. 别人的Linux私房菜(12)正则表达式与文件格式化处理

    vi gerp awk sed支持正则表达式   cp ls不支持,只能使用bash本身的通配符 正则表达式分为基础正则表达式和拓展正则表达式 使用正则表达式注意语系的影响 http://cn.lin ...

  9. mac开发常用工具和插件记录

    1.alfred 是 Mac 系统上一款专注于效率提升的著名应用,它能帮你快速打开网页.快速进行自定义搜索.查看剪贴板历史.快速查询单词等等.Alfred 提供的功能虽然很多,但目的只有一个 —— 那 ...

  10. 让photoshop cc 支持 webp格式

    下载WebP.8bi文件,看PS cc 是32位还是64位,找到对应的文件. brushes8.com-2017-11-03_08-29-21_654098.7z 把  WebP.8bi 复制到pho ...