There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other number afterward until you reach the end of the list.

Repeat the previous step again, but this time from right to left, remove the right most number and every other number from the remaining numbers.

We keep repeating the steps again, alternating left to right and right to left, until a single number remains.

Find the last number that remains starting with a list of length n.

Example:

Input:
n = 9,
1 2 3 4 5 6 7 8 9
2 4 6 8
2 6
6 Output:
6

这道题是 LeetCode 第二次编程比赛的题,然而博主并没有做出来,博主用的方法是那种最笨的方法,用一个数组把n个数组都存起来,然后根据循环的奇偶来决定是从左还是从右删除,结果不幸超时 TLE 了。后来通过想大神请教和上网搜索,发现这道题用递归来做很简单,用一个 bool 型变量 left2right,为 true 表示从左往右,为 false 表示从右往左遍历。当n为1时,不论从左往右还是从右往左都返回1。如果n大于1,且是从左往右的话,返回2倍的对 n/2 的从右往左的遍历;如果是从右往左的话,稍稍麻烦一些,肯定还是要对 n/2 调用递归函数的,但是要分奇偶情况,如果n为奇数,返回2倍的对 n/2 的从左往右的遍历的值;如果n为偶数,2倍的对 n/2 的从左往右的遍历的值,再减去1。具体这样的原因,博主还在研究中,也不是太清楚:

解法一:

class Solution {
public:
int lastRemaining(int n) {
return help(n, true);
}
int help(int n, bool left2right) {
if (n == ) return ;
if (left2right) {
return * help(n / , false);
} else {
return * help(n / , true) - + n % ;
}
}
};

下面这种方法相当的叼,一行就搞定了简直丧心病狂啊。第一次从左往右删除的时候,奇数都被删掉了,剩下的都是偶数。如果对所有数都除以2,那么得到一个1到 n/2 的新数列。下一次从右往左删出,那么返回的结果应该是调用递归的结果 lastRemaining(n / 2) 在数组1到 n/2 之间的镜像。何为镜像,比如 1, 2, 3, 4 这个数字,2的镜像就是3, 1的镜像是4,参见代码如下:

解法二:

class Solution {
public:
int lastRemaining(int n) {
return n == ? : * ( + n / - lastRemaining(n / ));
}
};

下面这种迭代的解法是博主请教另一位大神的方法,个人感觉也非常叼,膜拜大神中,先来看两个简单的例子:

n = 8
1 2 3 4 5 6 7 8
   2    4    6   8
   2          6
               6
      
n = 7      
1 2 3 4 5 6 7
   2    4    6
         4

如果仔细观察,可以发现从左往右删的时候,每次都是删掉第一个数字,而从右往左删的时候,则有可能删掉第一个或者第二个数字,而且每删一次,数字之间的距离会变为之前的两倍。这里要做的是每次记录当前数组的第一个数字,而且再通过观察可以看出,从右往左删时,如果剩下的数字个数是偶数个时,删掉的是第二个数字;如果是奇数个的时候,删掉的是第一个数字。总结出了上述规律,就可以写出代码如下:

解法三:

class Solution {
public:
int lastRemaining(int n) {
int step = , res = ;
while (step * <= n) {
res += step;
step *= ;
if (step * > n) break;
if ((n / step) % == ) res += step;
step *= ;
}
return res;
}
};

再来看一种论坛上的高分解法,其实这种解法的本质跟上面那种解法一样的,这里多使用了两个变量,一个是布尔型变量 left2right,表示当前的方向,为 true 表示是从左往右删;另一个是整型变量 remain,表示当前还剩下的数字个数。当 remain 大于1的时候进行循环,res 表示的是当前剩下的左数第一个数字。根据之前的分析,当从左往右删除的时候,左边第一个数字一定会被删掉;而从右往左删时,如果剩下的数字个数是偶数个时,删掉的是第二个数字;如果是奇数个的时候,删掉的是第一个数字。这样只要判断 left2right 为 true,或者 remain 是奇数的时候,res 要加上 step,也就是当前数字之间的间隔数,每删除一次,step 都要自乘以2,同时 remain 要除以2,left2right 也要变成其相反的状态,参见代码如下:

解法四:

class Solution {
public:
int lastRemaining(int n) {
bool left2right = true;
int res = , step = , remain = n;
while (remain > ) {
if (left2right || remain % == ) res += step;
remain /= ;
step *= ;
left2right = !left2right;
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/390

类似题目:

https://leetcode.com/problems/elimination-game/

https://leetcode.com/problems/elimination-game/discuss/87128/C-1-line-solution-with-explanation

https://leetcode.com/problems/elimination-game/discuss/87121/O(logN)-solution.-clear-break-down

https://leetcode.com/problems/elimination-game/discuss/87120/one-line-java-solution-based-on-Josephus-Problem

https://leetcode.com/problems/elimination-game/discuss/87119/JAVA%3A-Easiest-solution-O(logN)-with-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 390. Elimination Game 淘汰游戏的更多相关文章

  1. 390 Elimination Game 淘汰游戏

    详见:https://leetcode.com/problems/elimination-game/description/ C++: 方法一: class Solution { public: in ...

  2. [LeetCode] Elimination Game 淘汰游戏

    There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number ...

  3. [leetcode] 390 Elimination Game

    很开心,自己想出来的一道题 There is a list of sorted integers from 1 to n. Starting from left to right, remove th ...

  4. 【LeetCode】390. Elimination Game 解题报告(Python)

    [LeetCode]390. Elimination Game 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/elimina ...

  5. Java实现 LeetCode 390 消除游戏

    390. 消除游戏 给定一个从1 到 n 排序的整数列表. 首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾. 第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数 ...

  6. leetcode 390. 消除游戏

    {20-01-29 19:22} class Solution { public int lastRemaining(int n) { return help(n); } public static ...

  7. 【leetcode】390. Elimination Game

    题目如下: 解题思路:对于这种数字类型的题目,数字一般都会有内在的规律.不管怎么操作了多少次,本题的数组一直是一个等差数列.从[1 2 3 4 5 6 7 8 9] -> [2 4 6 8] - ...

  8. [LeetCode] Burst Balloons 打气球游戏

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  9. [LeetCode] Game of Life 生命游戏

    According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...

随机推荐

  1. spring tomcat启动 请求处理

    onRefresh(); protected void onRefresh() { try { createEmbeddedServletContainer(); } } private void c ...

  2. EntityFrameworkCore 学习笔记之示例一

    直接贴代码了: 1. Program.cs using Microsoft.EntityFrameworkCore; using System; using System.Threading.Task ...

  3. 部署Azure环境Web应用程序不能直接访问JSON文件解决方案

    问题: 部署在Azure环境Web应用程序的JSON文件,直接通过浏览器或Web应用访问出现 404 的错误信息. 以下通过Firfox浏览器直接访问JSON文件返回的提示错误信息: “HTML 文档 ...

  4. webservice因引用Oracle.DataAccess.dll导致发布前预编译不通过

    这个问题最初是什么问题已经忘了,虽然就在几小时前/

  5. 基于WEB的网上购物系统-ssh源码

    基于WEB的网上购物系统主要功能包括:前台用户登录退出.注册.在线购物.修改个人信息.后台商品管理等等.本系统结构如下:(1)商品浏览模块:        实现浏览最新商品        实现按商品名 ...

  6. 前端开发JS——快速入门

    1.JS的核心标准ECMAScript        组成      ECMAScript------>核心语法标准      DOM------------->对文档节点的操作      ...

  7. OL7.7安装Oracle 11.2.0.4

    安装环境准备工具 yum –y install oracle-rdbms-server-11gR2-preinstall 创建目录 mkdir -p /u01/app/oracle/product/1 ...

  8. Nginx02(环境配置以及基本使用)

    一:Nginx环境配置 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet ...

  9. 感知哈希算法——Python实现【转】

    转自:https://blog.csdn.net/m_buddy/article/details/78887248 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  10. pdfium sdk调用方式

    FPDF_InitLibrary(NULL); FPDF_CreateNewDocument(); FPDF_DestroyLibrary();