一起刷力扣之【390. 消除游戏】

189 阅读1分钟

这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

题目

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:

  • 从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
  • 重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
  • 不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。 给你整数 n ,返回 arr 最后剩下的数字。

示例

输入:n = 9
输出:6
解释:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]

输入: n = 1
输出: 1

提示

  • 1 <= n <= 109^9

解题思路

该题最直观的解题方法,就是使用一个指针(result)来进行模拟操作,在每次排除掉一半的元素之后,指针根据步长(step),移动至下一存活元素的位置, 当只剩下一个元素时,返回最终结果。

1.gif

代码实现

class Solution {
    public static int lastRemaining(int n) {
        // 结果
        int result = 1;
        // 步长
        int step = 1;
        // 转向
        boolean direction = true;

        // 当元素数量大于1时,需要排除掉一半的元素
        while (n > 1) {
            if (direction) {
                // 正向,指针根据步长移动至下一元素处
                result = result + step;
            } else {
                // 反向,判断剩余数量是否为偶数
                // 偶数则指针不需要移动
                // 奇数则指针需要移动至下一存活元素处
                result = (n % 2 == 0) ? result : result + step;
            }
            // 转向
            direction = !direction;
            // 每次排除一半元素
            n = n >> 1;
            // 跳过排除掉的元素间隔
            step = step << 1;
        }

        // 返回结果
        return result;
    }
}

另外在力扣的题解区中,【宫水三叶】大佬使用约瑟夫环的思路来进行解题,一行代码搞定,对于最求最少代码量的小伙伴一定不能错过!

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

【宫水三叶】大佬题解原文地址:leetcode-cn.com/problems/el…

最后

寻找小伙伴一起打卡学习,2022一起加油!!!