[LeetCode] 1025. Divisor Game 除數游戲



Alice and Bob take turns playing a game, with Alice starting first.

Initially, there is a number N on the chalkboard.  On each player's turn, that player makes a move consisting of:

  • Choosing any x with 0 < x < N and N % x == 0.
  • Replacing the number N on the chalkboard with N - x.

Also, if a player cannot make a move, they lose the game.

Return True if and only if Alice wins the game, assuming both players play optimally.

Example 1:

Input: 2
Output: true
Explanation: Alice chooses 1, and Bob has no more moves.

Example 2:

Input: 3
Output: false
Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves.

Note:

  1. 1 <= N <= 1000

這道題說是愛麗絲和鮑勃在玩一個除數游戲,這愛麗絲和鮑勃估計就相當於我們的小明和小紅,或者是李雷和韓梅梅之類的吧,經常出現啊。說是最初有一個數字N,每次每個人選一個小於N且能整除N的數字x,並將N替換為 N-x,依次進行,直到某個人沒法進行了,則算輸了。現在給個任意的N,且愛麗絲先走,問愛麗絲能否贏得游戲。先來分析一個下得到什么數字的時候會輸,答案是當N變成1的時候,此時沒法找到小於N的因子了,則輸掉游戲。博主看到題后的第一個反應就是用遞歸,因為調用遞歸得到的結果是對手的勝負,若遞歸返回 false,則說明當前選手贏了,反之則當前選手輸了。但是遞歸的方法不幸超時了,因為有大量的重復計算在里面,我們需要緩存這些中間變量,以避免重復計算,可以使用遞歸加記憶數組來做,也可以使用迭代的寫法,那么就變成動態規划 Dynamic Programming 了。這里的 dp 數組定義很直接,dp[i] 表示起始數字為i時愛麗絲是否會贏,大小為 N+1,更新時從2開始就行,因為0和1都是 false,從2更新到N,對於每個數字,都從1遍歷到該數字,找小於該數的因子,不能整除的直接跳過,能整除的看 dp[i-j] 的值,若為 false,則 dp[i] 更新為 true,並 break 掉即可,參見代碼如下:


解法一:

class Solution {
public:
    bool divisorGame(int N) {
        vector<bool> dp(N + 1);
        for (int i = 2; i <= N; ++i) {
            for (int j = 1; j < i; ++j) {
                if (i % j != 0) continue;
                if (!dp[i - j]) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[N];
    }
};

其實這道題的終極解法就一行,直接判斷奇偶即可,若N是偶數愛麗絲一定能贏,奇數一定會輸。博主大概講一下原因吧,前面提到過了,若某個人拿到了1,則表示輸了,所以當拿到2的時候,一定會贏,因為取個因數1,然后把剩下的1丟給對手就贏了。對於大於2的N,最后都會先減小到2,所以其實這個游戲就是個爭2的游戲。對於一個奇數N來說,小於N的因子x一定也是個奇數,則留給對手的 N-x 一定是個偶數。而對於偶數N來說,我們可以取1,然后變成一個奇數丟給對手,所以拿到偶數的人,將奇數丟給對手后,下一輪自己還會拿到偶數,這樣當N不斷減小后,最終一定會拿到2,所以會贏,參見代碼如下:


解法二:

class Solution {
public:
    bool divisorGame(int N) {
        return N % 2 == 0;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1025


參考資料:

https://leetcode.com/problems/divisor-game/

https://leetcode.com/problems/divisor-game/discuss/274608/Simple-DP-Java-Solution

https://leetcode.com/problems/divisor-game/discuss/296784/Come-on-in-different-explanation-from-others


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM