题目
0, 1, …, n-1这n个数字(n>0)排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。
求出这个圆圈里剩下的最后一个数字。
样例
输入:n=5 , m=3
输出:3

解法一:模拟

c++中list容器用作双向链表
时间复杂度O(nm),空间复杂度O(n)

  1. #include <list>
  2. class Solution {
  3. public:
  4. int lastRemaining(int n, int m){
  5. list<int> l;
  6. for (int i = 0; i < n; i++)
  7. l.push_back(i);
  8. int cnt = m - 1;
  9. auto it = l.begin();
  10. while (l.size() > 1) {
  11. while (cnt--) {
  12. it++;
  13. if (it == l.end()) it = l.begin();
  14. }
  15. it = l.erase(it);
  16. if (it == l.end()) it = l.begin();
  17. cnt = m - 1;
  18. }
  19. return l.front();
  20. }
  21. };

解法二:DP

dp(n, m) 表示n个人, m为号的最后结果
每次删除一个人后重新编号
那么 dp(n, m) = (dp(n - 1, m) + m) % n
因为此时0的位置是原来m的位置
时间复杂度O(n),空间复杂度O(1)

  1. class Solution {
  2. public:
  3. int lastRemaining(int n, int m){
  4. int ans = 0;
  5. for (int i = 1; i <= n; i++) {
  6. ans += m;
  7. if (ans >= i) ans %= i;
  8. }
  9. return ans;
  10. }
  11. };
  12. // class Solution {
  13. // public:
  14. // int lastRemaining(int n, int m){
  15. // if (n == 0) return 0;
  16. // return (lastRemaining(n - 1, m) + m) % n;
  17. // }
  18. // };