LeetCode——390.消除游戏

大佬,牛!!!

  • 题目:给定一个n,然后从1开始删除元素,各一个删一个,一直到n,然后再反向删除,也是各一个删一个,都是从剩下的元素中的第一个开始删除,最终数组剩下一个元素,返回这个元素即可。[1, 2, 3, 4, 5, 6, 7, 8, 9]->[2, 4, 6, 8]->[2, 6]->[6]。
  • 我的思路:我是真的向构建一个数组了,然后看了n的范围1-10的9次方,瞬间直接放弃。遇到这种数学相关的,就比较难受,哎。然后还有一个规律需要发现一下,第一次没间隔1个数字就删除一个,第二次的是间隔两个,第三次是4个。
  • 大佬的思路:
    • 首先我们每一行弄完之后,剩下的都是一个等差数列,我们返回的一定是这个等差数列的a1,这一点一定要明确。看一下举例,我们最后剩下2,6,然后删除2之后,还剩下6,这个可以自己称为一个等差数列,他就是a1。至于为什么需要删除2,是因为第一个箭头是从左向右删除,第二个箭头是从右向左,第三个又是从左向右。
    • 然后我们换个例子,[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]->[2,4,6,8,10,12,14,16,18]->[4,8,12,16]->[8,16]->[8]
    • 然后再加上我能看到的那个规律,第一次间隔1个删除,第二次间隔2个删除,第三次间隔4个删除…,所以呢,第二个等差数列的a1是第一个a1+1=2,其实就是加了第一次的间隔;第三个等差数列的a1是之前的a1+2,其实就是加了第二次的间隔。
    • 然后再看最上面的例子,什么第三个数组[2,6],还是2,没有+间隔,主要是因为,我们再从[2, 4, 6, 8]->[2, 6]的时候,最开始的2并没有被删除,而[2,4,6,8,10,12,14,16,18]->[4,8,12,16]的时候,最开始的2是被删除了,那有啥区别呢,可以看到[2, 4, 6, 8]的时候,还剩下4(偶数)个数,而[2,4,6,8,10,12,14,16,18]剩下了9(奇数)个数,这样就明白了把。从左向右的时候是不需要考虑的,因为我们的下一个数组一定是自身加上间隔,但是从右向左的时候一定是要考虑的,我们需要看看之前的a1是不是被删除了,如果没有被删除,则他还是a1,如果删除了,那么就变成了a1+step。
  • 技巧:
    • 技巧就是等差数列吧,然后返回的是a1,这个技巧就是数学相关的了。哎,难受。
    • 还有就是,没遍历依次,剩下的元素的个数一定是int(之前的个数/2)。

伪代码

记录第一个等差数列的a1,也就是1
记录向左还是向右遍历,因为在向右的时候,会有特殊情况的。第一次是向右
记录间隔step,第一次的时候间隔是1
记录元素个数,cnt,第一次的时候一定是n
while循环,只要cnt不是1。一次while就是一行的删除
    如果是向右的话,下一个a1一定是现在的a1+间隔step
    如果是向左的话,需要判断,现在还有多少个元素,如果是偶数个则还是a1,否则就变成了a1+step。因为偶数的时候,上一个的a1是不被删除的。
    方向反转
    cnt要/2
    step要*2
return a1即可

java代码

class Solution {
    public int lastRemaining(int n) {
        int a1 = 1;// 每个等差数列的第一个元素
        boolean isToRigth = true;// 是不是向右
        int cnt = n;// 元素个数
        int step = 1;// 下一个等差数列的a1和本次等差数列a1的位置之间的距离,每次这个step都需要*2
        while (cnt > 1) {// 一个while就是一行的遍历
            if (isToRigth) {// 向右,则下一个等差数列的a1是a1+step
                a1 = a1 + step;
            } else {
                // 向左,则下一等差数列的a1还是a1+step,
                // 但是这时候有个特殊情况,就是如果当前是偶数的话,a1还是a1,因为删除的节点是a1+step,而a1不删除
                a1 = (cnt % 2 == 0) ? a1 : a1 + step;
            }
            isToRigth = !isToRigth;
            cnt /= 2;
            step *= 2;
        }
        return a1;
    }
}
  • 总结:这个题主要是结合了数学,然后技巧性比较高,并且还右一些判断。我是真的我从下手,忍不住了,大佬,牛!!!

你可能感兴趣的:(算法,leetcode,算法,java)