1 class Solution {
 2 public:
 3     int lastRemaining(int n) {
 4         if (n == 1) return 1;
 5         return 2 * (n / 2 + 1 - lastRemaining(n / 2));
 6 
 7         // vector<int> t;
 8         // for (int i = 1; i <= n; i++) t.push_back(i);
 9         // bool flag1 = true;
10         // while (t.size() > 1) {
11         //     // cout << t.size() << endl;
12         //     vector<int> tmp;
13         //     bool flag2 = false;
14         //     if (flag1) {
15         //         for (int i = 0; i < t.size(); i++) {
16         //             if (flag2) tmp.push_back(t[i]);
17         //             flag2 = !flag2;
18         //         }
19         //     } else {
20         //         for (int i = t.size() - 1; i >= 0; i--) {
21         //             if (flag2) tmp.insert(tmp.begin(), t[i]);
22         //             flag2 = !flag2;
23         //         }
24         //     }
25 
26         //     t.clear();
27         //     t = tmp;
28         //     flag1 = !flag1;
29         // }
30 
31         // return t[0];
32     }
33 };

算法思路:数学题。

1.设n个数时,从左到右开始执行剩下的数为f1(n),将n个数反转后(即:n,n-1,...,1),从左到右执行剩下的数为f2(n)
2.则,f1(n)和f2(n)剩下的数,在他们在各自原数组中的下标一定一样,即两者剩余的数都是下标i位置处的元素。1,...,n和n,...,1两个相同下标的元素相加为n+1
3.那么f2(n)的元素怎么得到?对于2n个元素,执行一次从左到右之后,剩余的元素除以2,可以得到1,...,n的元素。
4.如果继续执行,相当于对1,...,n的元素从右到左开始执行(因为第一次已经从左到右执行了),等价于:对于1,...,n元素从右到左执行的结果*2,即:f1(2n) = 2 * f2(n)
5.所有得到递推式:f1(n) + f2(n) = n + 1 又由于f2(n) * 2 = f1(2n) 所以:f1(n) + f1(2n) / 2 = n + 1;
6.用n/2替换n得到:f1(n/2) + f1(n) / 2 = n / 2 + 1 -----> f1(n) = 2 * (n / 2 + 1 - f1(n / 2))

参考:https://leetcode-cn.com/problems/elimination-game/solution/cpp-ke-neng-bi-jiao-hao-li-jie-yi-dian-de-si-lu-by/

posted on 2020-04-09 10:40  Sempron2800+  阅读(217)  评论(0编辑  收藏  举报