面试题62. 圆圈中最后剩下的数字
0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
解题思路: 这是《剑指offer》书上的原题,书上的解法一采取的是用双链表模拟约瑟夫环,但是此算法的时间复杂度为O(M∗N)O(M*N)O(M∗N),OJ会超时,代码也贴一下。
class Solution {
public:
int lastRemaining(int n, int m) {
list<int> l;
for (int i = 0; i < n; ++i) {
l.push_back(i);
}
auto p = l.begin();
while (l.size() > 1) {
for (int i = 0; i < m - 1; ++i) {
++p;
if (p == l.end()) p = l.begin();
}
p = l.erase(p);
if (p == l.end()) p = l.begin();
}
return *p;
}
void print(list<int> l) {
for (auto t : l) {
cout << t << ",";
}
cout << endl;
}
};
OJ只通过了解法二,解法二直接通过数学推导得到公式。
class Solution {
public:
int lastRemaining(int n, int m) {
if (n == 1) return 0;
return (lastRemaining(n - 1, m) + m) % n;
}
};