【Leetcode-每日一题】消除游戏

消除游戏
难度:中等
【Leetcode-每日一题】消除游戏_第1张图片
没想到新年第二题就碰壁了。
尝试枚举找出规律,没有得逞。只能看题解了
题解中提到了约瑟夫环,但我觉得有点晦涩难懂,所以采用另外一种方式,思路如下:
每个回合更新和记录head变量,当数组的总数变为1时,head就是最后的一个数
什么时候更新这个head变量呢?
当我们从左边开始移除的时
当我们从右边开始移除并且剩余的数的总数 number % 2 == 1时
比如 2 4 6 8 10,我们从10开始移除,我们将会移除10,6,2,head被移除并且变为4
比如 2 4 6 8 10 12,我们从12开始移除,我们将会移除12,8,4,head仍然是2
然后我们发现了一个更新head的规则

例如:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

初始化变量 head = 1,left = true,step = 1,n = 24
left用来判断是从左边开始移除还是从右边开始移除(true表示从左边开始)
step用来表示head移动步长
n在题目中给出,我们用来记录数组数字的总数

我们第一次从左边开始移除,我们肯定需要把head移到下一个位置(head = head + step
所以我们第一次循环将得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - > 2 4 6 8 10 12 14 16 18 20 22 24
head = 2, left = false, step = 1 * 2 = 2, n = n / 2 = 12
第二次循环,我们从右边开始移除,在什么情况下我们需要移动头部?
只有 n % 2 == 1,在这种情况下我们有 12 % 2 == 0,我们不修改head
所以第二次循环之后我们将得到:
2 4 6 8 10 12 14 16 18 20 22 24 - > 2 6 10 14 18 22
head = 2, left = true, step = 2 * 2 = 4, n = n / 2 = 6
第三次循环,我们从左边开始移除,第三次循环我们将把head移动到下一个位置
第三次循环之后我们将得到:
2 6 10 14 18 22 - > 6 14 22
head = 6, left = false, step = 4 * 2 = 8, n = n / 2 = 3
第四次循环,我们从右边开始移除,注意head:
我们得到 n(3) % 2 == 1,所以我们知道需要将head移动到下一个位置
这次循环之后,我们将得到:
6 14 22 - > 14
head = 14, left = true, step = 8 * 2 = 16, n = n / 2 = 1
n 等于 1, 循环结束,return head
有了思路,代码其实就很好实现了。
代码如下:

	public int lastRemaining(int n) {
        int head = 1;
        boolean left = true;
        int step = 1;
        while(n>1){
            if (left || n % 2 ==1){
                head = head+step;
            }
            step = step *2;
            n = n/2;
            left = !left;
        }
        return head;
    }

执行结果:通过
【Leetcode-每日一题】消除游戏_第2张图片

你可能感兴趣的:(#,LeetCode-每日一题,leetcode,算法)