leetcode 390. 消除游戏

给定一个从1 到 n 排序的整数列表。
首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。
第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。
我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
返回长度为 n 的列表中,最后剩下的数字。

示例:

输入:
n = 9,
1 2 3 4 5 6 7 8 9
2 4 6 8
2 6
6

输出:
6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/elimination-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

1:传入的参数是n,每次都山区掉 n/2个数字。

2:若剩余的数字是奇数个,则从左测或者从右侧删除的结果相同。迭代为 n = 2n; 若剩余的数字是偶数个,从右侧删除。迭代为 n = 2n - 1;

3:若从左侧删除,剩余的数列 arr2 是 原来数列 arr 的长度的一半,

例如 原来的数组是 2,4,6,8,10 变成了 4, 8,

4:若从右侧删除,

例如 原来的数组是 2,4,6,8,10,12 变成了 2,6,10,

数组 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20(length = 20)

第一次 2,4,6,8,10,12,14,16,18,20 (length 10, value = 2n)

从左侧删除, 所以上一次的n 用2n 代替,1(2n) = 2n

第二次 2,6,10,14,18 (length 5, value = 4n - 2)

因为上一步的长度 10 是偶数,并且从右侧删除, 所以上一次的n 用2n - 1代替,2(2n - 1)= 4n - 2

第三次 6,14 (length 6, value = 8n - 2)

从左侧删除, 所以上一次的n 用2n 代替,4(2n)- 2 = 8n - 2

第四次 6 (length 1, value = 16n - 10) 因为上一步的长度 2 是偶数,并且从右侧删除, 所以上一次的n 用2n - 1代替,8*(2n - 1) - 2= 16n - 10

以上则为通项公式。

    public int lastRemaining(int n) {
        boolean flag = false;
        int i = 1;
        int value = 0;
        while (n != 1) {
            if ((n & 1) == 0 && flag) {
                value = value + i;
            }
            n >>= 1;
            i <<= 1;
            flag = !flag;
        }
        return i - value;
    }

posted @ 2021-06-30 12:04  旺仔古李  阅读(87)  评论(0编辑  收藏  举报