LeetCode : 390. 消除游戏(Elimination Game)分析和解答

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/afei__/article/details/83689502

390. 消除游戏

给定一个从1 到 n 排序的整数列表。

首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。

第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。

我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。

返回长度为 n 的列表中,最后剩下的数字。

实例:

输入:

n = 9,

1 2 3 4 5 6 7 8 9

2 4 6 8

2 6

6

输出:

6

一、解答

思路1:

先说一个不好的实现。首先看到这个题,很容易联想到使用一个链表,然后依次删一个跳一个,正序倒序来回执行,直到长度为 1 时返回。这样确实也可以实现,但是耗时太长了,无法满足需求。

思路2:

上述思路行不通,我们只好想别的办法了。当我们仔细观察后,其实这里面隐藏着很强的规律。我们先把答案贴出来,下面再详细证明。

实现:

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

二、证明

假如输入为 n,我们使用 f(n) 表示 从左到右(forward) 的最终结果,使用 b(n)表示 从右到左(backward) 的最终结果。则

规律1: 当 n = 1 时,存在 f(n) = 1, b(n) = 1

规律2: 对于任意 n,存在 f(n) + b(n) = n + 1

我们先 假设 这条规律是成立的(因为我们会在后面证明它)。我们先来看一些例子:

当 n = 1 时,由定理 1 可知:f(n) = 1, b(n) = 1,存在 f(n) + b(n) = n + 1 = 2。
当 n = 2 时,f(n) = 2, b(n) = 1,存在 f(n) + b(n) = n + 1 = 3。
当 n = 3 时,f(n) = 2, b(n) = 2,存在 f(n) + b(n) = n + 1 = 4。
当 n = 4 时,f(n) = 2, b(n) = 3,存在 f(n) + b(n) = n + 1 = 5。

规律3: 对于 n > 2 的情况下,f(n) = 2 * b(n / 2)

假如现在有一个输入为 [1,2,3,4,5,6],第一次删除后结果为 [2,4,6],可视为 2 * [1,2,3],而我们知道下一次是 “从右到左” 的,即我们可以使用 b(3) 表示 [1,2,3] “从右到左” 的执行结果,则 f(6) = 2 * b(3)
同样,如果输入为 [1,2,3,4,5,6,7],第一次删除后结果同上,也有 f(7) = 2 * b(3)
那么,对于任意数 k,我们其实都可以按照上述方式将 f(k) 表示为:f(k) = 2 * b(k / 2)

证明规律2正确:

我们想要证明 f(n) + b(n) = n + 1 成立,又已知 f(n) = 2 * b(n / 2)
我们可以将他们表示为:b(n) = n + 1 - f(n) = n + 1 - 2 * b(n / 2)f(n) = 2 * b(n / 2) = 2 * (n / 2 + 1 - f(n / 2))
即:f(n) + b(n) = n + 1 可以表示为:2 * (n / 2 + 1 - f(n / 2)) + n + 1 - 2 * b(n / 2) = n + 1
化简可得:f(n / 2) + b(n / 2) = n / 2 + 1

所以:欲证明 f(n) + b(n) = n + 1 成立,即证明 f(n / 2) + b(n / 2) = n / 2 + 1 成立。

证明过程:

使用数学归纳法,先从前面几个例子开始,即:

当 n = 1 时,已知 f(1) = 1, b(1) = 1,f(1) + b(1) = 2 成立。
当 n = 2 时,已知 f(2) = 2, b(2) = 1,f(2) + b(2) = 3 成立。
当 n = 3 时,已知 f(3) = 2, b(3) = 2,f(3) + b(3) = 4 成立。

当 n = k 时,已知 f(k / 2) + b(k / 2) = k / 2 + 1 成立,所以 f(k) + b(k) = k + 1 成立。

最终,对于任意值 n,我们都可以说 f(n) + b(n) = n + 1。

结论:

当 n = 1 时:

f(n) = b(n) = 1。

当 n > 1 时:

f(n) = 2 * (n / 2 + 1 - f(n / 2))

b(n) = n + 1 - 2 * b(n / 2)

三、项目地址:

https://github.com/afei-cn/LeetCode/tree/master/390.%20Elimination%20Game

四、原题地址:

https://leetcode-cn.com/problems/elimination-game/description/

猜你喜欢

转载自blog.csdn.net/afei__/article/details/83689502