博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LeetCode] Elimination Game 淘汰游戏
阅读量:6569 次
发布时间:2019-06-24

本文共 2180 字,大约阅读时间需要 7 分钟。

 

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 92 4 6 82 66Output: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 == 1) return 1;        if (left2right) {            return 2 * help(n / 2, false);        } else {            return 2 * help(n / 2, true) - 1 + n % 2;        }    }};

 

下面这种方法相当的叼,一行就搞定了简直丧心病狂啊。第一次从左往右删除的时候,奇数都被删掉了,剩下的都是偶数。如果我们对所有数都除以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 == 1 ? 1 : 2 * (1 + n / 2 - lastRemaining(n / 2));        }};

 

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

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 base = 1, res = 1;        while (base * 2 <= n) {            res += base;            base *= 2;            if (base * 2 > n) break;            if ((n / base) % 2 == 1) res += base;            base *= 2;        }        return res;    }};

 

类似题目:

 

转载地址:http://ohpjo.baihongyu.com/

你可能感兴趣的文章
Laravel5.5 使用第三方Vendor添加注册验证码
查看>>
06- Linux下sublime下载与使用
查看>>
前端文摘:Web 开发模式演变历史和趋势
查看>>
将图片序列转化为视频文件
查看>>
jQuery的文档操作***
查看>>
js 小数取整,js 小数向上取整,js小数向下取整
查看>>
vue-cli3.0
查看>>
window.location.replace vs window.location.href
查看>>
CVPR 2018:阿里提出应用 LocalizedGAN 进行半监督训练
查看>>
被劫持的wordpress.com账户被用来感染站点
查看>>
分享一下最近看的东西
查看>>
《大数据、小数据、无数据:网络世界的数据学术》一 第2章 何为数据 2.1 引言...
查看>>
寓教于乐的顶峰:新一届大学生集群竞赛火热开战
查看>>
《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一第1章 职业发展机会和团队建设...
查看>>
HBase BlockCache系列 - 探求BlockCache实现机制
查看>>
【参与有奖】您用的MySQL、MongoDB、Redis等服务被勒索过吗?
查看>>
Java核心技术卷I基础知识1.2.6 体系结构中立
查看>>
Libvirt 虚拟化库介绍
查看>>
《Spring 5 官方文档》26. JMS(一)
查看>>
《Python Cookbook(第2版)中文版》——1.11 检查一个字符串是文本还是二进制
查看>>