(剑指Offer)面试题45:圆圈中最后剩下的数字
题目:
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:圆圈中最后剩下的数字的更多相关文章
- 【剑指Offer】孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python)
[剑指Offer]孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-in ...
- 《剑指offer》面试题45 圆圈中最后剩下的数字(Java版本)
引言 这道题网上的讲解都是直接抄书,没意思,所以想自己写一写,补充一下,便于自己理解.另外,大家都忽略了经典解法,虽然这种解法效率不及第二种,但是我觉得在项目当中阅读性其实很重要,牺牲一点点效率保证代 ...
- 【剑指Offer】46、圆圈中最后剩下的数
题目描述: 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后 ...
- 剑指Offer 46. 孩子们的游戏(圆圈中最后剩下的数) (其他)
题目描述 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...
- [剑指offer] 46. 孩子们的游戏(圆圈中最后剩下的数)
题目描述 随机指定一个数m,让编号为0的小朋友开始报数.每次喊到m-1的那个小朋友要出列,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友 ...
- 【剑指offer】孩子们的游戏(圆圈中最后剩下的数)
题目描述 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...
- C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解
剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...
- Java实现 LeetCode 面试题62. 圆圈中最后剩下的数字(约瑟夫环)
面试题62. 圆圈中最后剩下的数字 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成一个圆 ...
- 【LeetCode】面试题62. 圆圈中最后剩下的数字
题目:面试题62. 圆圈中最后剩下的数字 这题很有意思,也很巧妙,故记录下来. 官方题解思路,是约瑟夫环的数学解法: 我们将上述问题建模为函数 f(n, m),该函数的返回值为最终留下的元素的序号. ...
- 剑指Offer:面试题15——链表中倒数第k个结点(java实现)
问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...
随机推荐
- java_22 Map接口
1Map Collection是孤立存在的,向集合中存储元素是一个一个放进去的 Map中的集合存储是成对的,可以通过键找到值.即将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值 ...
- c++矩阵运算库Eigen简介
C++矩阵运算库Eigen介绍 C++中的矩阵运算库常用的有Armadillo,Eigen,OpenCV,ViennaCL,PETSc等.我自己在网上搜了一下不同运算库的特点,最后选择了Eigen.主 ...
- str 转 md5
@interface NSString (MD5) + (NSString *)md5To32bit:(NSString *)str; @end @implementation NSString (M ...
- 《笨方法学Python》加分题15
本题本题开始涉及文件的操作,文件操作是一件危险的事情,需要仔细细心否则可能导致重要的文件损坏. 本题除了 ex15.py 这个脚本以外,还需要一个用来读取的文件 ex15_sample.txt 其内容 ...
- [模板]LCA
洛谷P3379 注意:不能与LCA搞混(打久了就会发现两个还是有很大区别的) 位运算一定要加括号! for循环从0到logn还是从logn到0看当前的状态更适合哪种 第53行预处理一定要注意!(因为没 ...
- iPhone屏幕分辨率和适配规则 图片文字适配
基本概念 - 逻辑分辨率 pt (point),物理分辨率 px (pixel) - 缩放因子 scale 或者 dpr, scale ≈ px / pt - 缩放采样 例如 iPhone 6 Plu ...
- ScheduledExecutorService--目前最理想的定时任务实现方式
ScheduledExecutorService 理想的定时任务实现方式 : 通过线程池的方式来执行任务的 可以灵活的设定第一次执行任务延迟时间 提供了良好的约定,以便设定定时执行的间隔时间代码实现: ...
- 部署eclipse项目到tomcat
1.为了以防万一,将本地tomcat版本及其jdk版本与服务器上的版本最好是相同的 2.在本地eclipse下运行项目即可发布(注意(1)数据库连接的是服务器数据库还是本地数据库(2)运行项目前先cl ...
- js中push和pop的用法
push: 将新元素追加到一个数组中,并返回新的数组长度: 语法:arrayObj.push([item1 [item2 [. . . [itemN ]]]]) var number; var my_ ...
- 基于esp32的IIC通讯
本文源码地址在:http://download.csdn.net/download/noticeable/9962029 IIC 通讯应该是当代比较常用的几种通讯方式之一,其无需特殊的IO接口,连线方 ...