题目:
0、1…n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例子:
如0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3.
链接:
剑指Offer(第2版):P300
思路标签:
- 算法:循环链表模拟、寻找规律
解答:
1. 用环形链表模拟圆圈(效率低+)
- 这个题目是有名的约瑟夫环问题;
- 我们使用环形链表来模拟环的过程;
- 可以使用STL中的list来实现,但需要注意在处理的过程中,扫描到末尾的时候,重新连接到首部;
- 使用iterator来进行链表的遍历;
- 同时需要注意处理的边界问题。
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if (n < 1 || m < 1)
return -1;
list<int> numbers;
for (int i = 0; i < n; ++i)
numbers.push_back(i);
list<int>::iterator current = numbers.begin();
list<int>::iterator next;
while (numbers.size() > 1) {
for (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. 寻找规律求解(O(n)时间复杂度)简单高效
- 寻找规律的过程见剑指offer第二版P302。
class Solution {
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;
return last;
}
};