剑指offer系列36:孩子们的游戏

书上说这是著名的约瑟夫环问题。这个要频繁删除操作,所以用list做就很容易想到了。list是单向的,所以当迭代器走到尾部的时候,再让它回到头部就可以形成环。

 1 class Solution {
 2 public:
 3     int LastRemaining_Solution(int n, int m)//n个人,从第一个开始数,第m个退出,循环往复
 4     {
 5         if (n == 0)
 6             return -1;
 7         list<int> li;
 8         //定义一个迭代器,用迭代器找到m
 9         //重新定义迭代器指向上一个迭代器的下一个
10         //删除第一个迭代器的m位
11         for (int i = 0; i < n; i++)
12             li.push_back(i);
13 
14         auto f = li.begin();
15         //li.erase(*(f + m));
16         while (li.size() > 1)
17         {
18             for (int i = 0;i<m-1;  i++)//寻找第m个数
19             {
20                 f++;
21                 if (f == li.end())//循环起来
22                     f = li.begin();
23             }
24             auto next =++ f;//定义一个新的迭代器,保存第一个迭代器的下一个的值。
25                                        //因为下一步有list的删除操作会令第一个定义的迭代器失效
26             if (next == li.end())
27                 next = li.begin();
28             f--;
29             li.erase(f);
30             f = next;
31         }
32 
33         return *f;
34     }
35 };

看到剑指offer上的第二种解法。将这个题目推到出一个递归的公式。这样关键是要想到递归,其次想到递归要会推导公式,数学好难,o(╥﹏╥)o不过这个代码确实很简洁,想清楚思路用这种方法做很有用。

 1 class Solution {
 2 public:
 3     int LastRemaining_Solution(int n, int m)
 4     {
 5         if (n <1||m<1)
 6             return -1;
 7         int last = 0;
 8         for (int i = 2; i <= n; i++)
 9             last = (last + m) % i;//计算每一轮的值
10         return last;
11     }
12 };

 

posted @ 2019-07-19 14:48  妮妮熊  阅读(255)  评论(0编辑  收藏  举报