题目:

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、环形链表

#include <iostream>
#include <list>
using namespace std; int lastRemaining(unsigned int n,unsigned int m){
if(n<1 || m<1)
return -1; std::list<int> numbers;
for(unsigned int i=0;i<n;i++)
numbers.push_back(i); std::list<int>::iterator current=numbers.begin();
std::list<int>::iterator next;
while(numbers.size()>1){
for(unsigned int i=1;i<m;i++){
current++;
if(current==numbers.end())
current=numbers.begin();
}
next=++current;
if(next==numbers.end())
next=numbers.begin(); --current;
numbers.erase(current);
current=next;
}
return *(current);
} int main()
{
cout << lastRemaining(5,3) << endl;
return 0;
}

2、映射规律,动态规划

int lastRemaining_1(unsigned int n,unsigned int m){
if(n<1 || m<1)
return -1; int last=0;
for(int i=2;i<=n;i++){
last=(last+m)%i;
}
return last;
} int lastRemaining_2(unsigned int n,unsigned int m){
if(n<1 || m<1)
return -1;
if(n==1)
return 0;
return (lastRemaining_2(n-1,m)+m)%n;
}

在线测试OJ:

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

AC代码:

1、环形链表

class Solution {
public:
int LastRemaining_Solution(unsigned int n, unsigned int m)
{
if(n<1 || m<1)
return -1; std::list<int> numbers;
for(unsigned int i=0;i<n;i++)
numbers.push_back(i); std::list<int>::iterator current=numbers.begin();
std::list<int>::iterator next; while(numbers.size()>1){
for(unsigned int i=1;i<m;i++){
++current;
if(current==numbers.end())
current=numbers.begin();
} next=++current;
if(next==numbers.end())
next=numbers.begin(); --current;
numbers.erase(current);
current=next;
} return *current;
}
};

2、序列规律,动态规划

class Solution {
public:
int LastRemaining_Solution(unsigned int n, unsigned int m)
{
if(n<1 || m<1)
return -1;
int last=0;
for(int i=2;i<=n;i++)
last=(last+m)%i; return last;
}
};
class Solution {
public:
int LastRemaining_Solution(unsigned int n, unsigned int m)
{
if(n<1 || m<1)
return -1;
if(n==1)
return 0; return (LastRemaining_Solution(n-1,m)+m)%n;
}
};

(剑指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. Spring源码-循环依赖源码解读

    Spring源码-循环依赖源码解读 笔者最近无论是看书还是从网上找资料,都没发现对Spring源码是怎么解决循环依赖这一问题的详解,大家都是解释了Spring解决循环依赖的想法(有的解释也不准确,在& ...

  2. rpc和http

    rpc,远程过程调用,分布式各服务在不同的节点,因为不在同一进程中,所以节点间的调用需要通过网络进行传输,rpc是基于tcp/ip的,通过长连接进行通信.客户端需要缓存服务端的ip和端口,服务端也要缓 ...

  3. python环境问题(pycharm)

    一.问题 我们在使用python的时候会遇到环境配置问题.如何可以一劳永逸,是我们解决问题的基本思想. 二.解决1.新建环境: 2.添加环境:选择需要的环境,可以是conda,亦可以是virtual. ...

  4. ActiveMQ_5死信队列

    activemq死信队列 DLQ-死信队列(Dead Letter Queue)用来保存处理失败或者过期的消息. 出现以下情况时,消息会被redelivered: A transacted sessi ...

  5. selenium之生成html测试报告--testng.xsl

    自制版制作步骤: 1.首先下载一个文件名为testng.xslt-1.1.zip testng.xslt-1.1我在印象笔记里面备份了一份 打开testng.xslt中lib文件夹,找到saxon-8 ...

  6. ABP框架系列之三十:(Javascript-API-Javascript-API)

    ASP.NET Boilerplate provides a set of objects and functions that are used to make javascript develop ...

  7. Codeforces Round #541--1131F. Asya And Kittens(基础并查集)

    https://codeforces.com/contest/1131/problem/F #include<bits/stdc++.h> using namespace std; int ...

  8. Hadoop 系列文章(一) Hadoop 的安装,以及 Standalone Operation 的启动模式测试

    以前都是玩 java,没搞过 hadoop,所以以此系列文章来记录下学习过程 安装的文件版本.操作系统说明 centos-6.5-x86_64 [bamboo@hadoop-senior opt]$ ...

  9. System.exit(int status)

    这个方法是用来结束当前正在运行中的Java虚拟机 System.exit(0); /* 实参为0表示正常终止 */ System.exit(1); /* 实参为非0表示异常终止 */

  10. 背水一战 Windows 10 (68) - 控件(控件基类): UIElement - Pointer 相关事件, Tap 相关事件, Key 相关事件, Focus 相关事件

    [源码下载] 背水一战 Windows 10 (68) - 控件(控件基类): UIElement - Pointer 相关事件, Tap 相关事件, Key 相关事件, Focus 相关事件 作者: ...