Leetcode笔记2-消除游戏

消除游戏

题目描述

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:
从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
给你整数 n ,返回 arr 最后剩下的数字。

思路

观察到经过几轮删除之后,序列依旧是是等差数列,并且相邻两个数的差值为2的n-1次方(n为轮次)。
并且正序删除后,首项一定会变为原首相加上公差,而末项则分为:偶数项,末项不变;奇数项,原末项被删除,变为原末项减去公差。
反序删除也类似,末项一定删除变为原末项减去公差,而首项分为:偶数项,首相不变;奇数项,原首项被删除,变为原首项减去公差。
所以每次删除之后可以算出首尾项,并且知道公差,也算是变相的知道了每次删除之后剩的序列到底是什么。
最后,根据如果首相和末项的值是否相等来判断序列是不是只剩下一个项了。

其实还可以将算法简化一些,就是由于每次删除之后,序列个数:n%2,所以知道首项、公差、个数也可以知道整个序列,所以没有必要再对末项进行过多的操作了,循环结束条件也可以改为由序列个数决定。

以下代码是未简化的版本。

具体实现

int lastRemaining(int n){
    int num = n,i=1;
    int first=1,end=n;
    int turn = 0;//正向还是逆向
    while(first!=end){
        
        if(num%2==0){
            if(turn==0){
                first=first+i;
                //end=end;
            }else{
                //first=first;
                end=end-i;
            }            
        } else{
            first=first+i;
            end=end-i;
            }
            
        num=num/2;
        turn=(turn+1)%2 ;
        i=i*2;
    }
    return first;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值