圆圈中最后剩下的数字 【微软面试100题 第十八题】
题目要求:
0,1,...,n-1这n个数排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删词第3个数字,则删除的前四个数字一次是2、0、4、1,因此最后剩下的数字是3.
参考资料:剑指offer第45题
题目分析:
方法1:用环形链表模拟圆圈,链表可以用c++的STL库中的list来表示,删除链表其中一个结点之后,链表还是连续的。
方法2:定义f(n,m),表示每次在n个数字0,1,...,n-1中每次删除第m个数字最后剩下的数字。
先给出关系公式:
可以这样理解:从序列f(n):0~n-1中删除第m个数后,剩下为序列m,m+1,..,n-1,0,1,...,m-2,即序列f(n-1)+m.因此f(n,m) = [f(n-1,m)+m]%n,是采用的映射关系来递推的。
代码实现:

#include <iostream> #include <list> using namespace std; int LastRemaining(unsigned int n,unsigned int m); int LastRemaining2(unsigned int n,unsigned int m); int main(void) { //cout << LastRemaining(5,3) << endl; cout << LastRemaining2(5,3) << endl; return 0; } //方法1 int LastRemaining(unsigned int n,unsigned int m) { if(n<1 || m<1) return -1; unsigned int i = 0; list<int> nums; for(i= 0;i<n;i++) nums.push_back(i); list<int>::iterator cur = nums.begin(); while(nums.size()>1) { for(int i = 1;i<m;i++) { cur++; if(cur==nums.end()) cur = nums.begin(); } list<int>::iterator next = ++cur; if(next == nums.end()) next = nums.begin(); --cur; nums.erase(cur); cur = next; } return *cur; } //方法2 int LastRemaining2(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; }
很多时候不是我们做不好,而是没有竭尽全力......
分类:
【微软面试100题】
posted on 2014-10-28 19:18 tractorman 阅读(1233) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?