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. PDF文件添加二维码水印教程

    maven配置iText的jar,主要不是所有私服都有iText的jar,maven仓库没有的,可以去https://mvnrepository.com/artifact/com.itextpdf/i ...

  2. IDEA快速修复错误快捷键

    有的时候在IDEA中编写代码,会出现错误提示,比如需要处理异常 将光标移动到出错,也就是划红线的地方,行首会出现一个小灯泡,点击会出现图二,可以按照提示进行修复

  3. C# SmtpClient 发邮件

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. C# in 参数修饰符

    in 修饰符记录: 新版C# 新增加的 in 修饰符:保证发送到方法当中的数据不被更改(值类型),当in 修饰符用于引用类型时,可以改变变量的内容,单不能更改变量本身. 个人理解:in 修饰符传递的数 ...

  5. linux 如何指定nologin用户执行命令

    在linux中建立网站时,我们一般分配一个www之类的用户给网站应用程序. 如果我们使用root或者具有管理员权限的账号在网站目录下去创建文件时,会遇到各种权限问题. 这时我们可以切换到www用户,这 ...

  6. Error: Opening Robot Framework log failed on mac jenkins

    For resolve your problem you must : Connect on your jenkins url (http://[IP]:8080/) Click on Manage ...

  7. .NET开发框架(六)-架构设计之IIS负载均衡(视频)

    前面有关注我们公众号文章的朋友应该都知道,我们的分布式应用服务可以通过Ocelot网关进行负载均衡,这种方式属于应用级别的实现. 而今天我们给大家介绍的是平台级别的实现,并且我们首次使用视频方式进行讲 ...

  8. 将多个sass文件合并到一个文件中

    将多个sass文件合并到一个文件中 应用场景:制作angular npm包的时候,定义的一些全局样式,自定义主题色这类的情况下,多个scss文件会要合并成一个文件并写到dist文件里,发布到仓库中. ...

  9. 删除Win10远程桌面中的无用的IP列表

    运行中,输入regedit,然后找到这个位置(也可在任务管理器的地址栏中,直接输入下面的地址),便可删除远程桌面中列出的一些无用的IP地址. 计算机\HKEY_CURRENT_USER\Softwar ...

  10. 云顶之弈换中立python脚本

    import pynput keyboard = pynput.keyboard.Controller() mouse = pynput.mouse.Controller() def on_relea ...