LeetCode-消除游戏

1,295 阅读2分钟

算法记录

LeetCode 题目:

  列表 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]

二、分析

  • 这个题是需要找规律的,[1, n] 之间的数其实是一个等差数列,然后我们间隔一个删掉一个,那么就会将其中的所有奇数全部删掉了,剩下的所有元素都是偶数且会组成一个 步长 * 2数量 / 2 的一个等差数列。
  • 这时候如果我们假设首先是第一个元素会被保存下来,那这一轮结束之后他就会加上一个 Step 来跳过被删除的可能。
  • 现在进行第二轮删除就要注意情况了,因为前一轮删除时可能最后一个删除是在当前留下队列的后面的,那也就是剩余队列的第一个元素相邻不用删除,但是如果是在留下队列的前面,剩余队列的第一个元素间隔需要删除,以此更新了我们预期留下的值,要么保持不变,要么就是再加上一个新的 Step。
  • 以循环迭代,当奇数次删除就第一种情况,偶数次删除就是第二种分情况讨论,直到当前元素个数唯一,就是剩余的那个元素输出即可。
class Solution {
    public int lastRemaining(int n) {
        int ret = 1, k = 0, step = 1;
        while(n > 1) {
            if(k % 2 == 0) {
                ret += step;
            } else {
                ret = (n % 2 == 0) ? ret : ret + step;
            }
            k++;
            step <<= 1;
            n >>= 1;
        }
        return ret;
    }
}

总结

找规律。