1. 程式人生 > >LeetCode : 390. 消除遊戲(Elimination Game)分析和解答

LeetCode : 390. 消除遊戲(Elimination Game)分析和解答

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)

專案地址:

原題地址: