解題說明
Stone Game
題目描述:Alice 和 Bob 輪流從一排石頭堆中取石頭,每次只能取最左或最右的一堆。石頭堆數為偶數,總石頭數為奇數(保證不會平局)。Alice 先手。兩人都以最優策略行動,判斷 Alice 是否能贏。
解題思路:
數學觀察(最優解):Alice 一定能贏!將石頭堆按位置分為奇數位和偶數位,Alice 先手可以選擇一直拿奇數位或一直拿偶數位的石頭。由於總數為奇數,奇數位和偶數位的總和不相等,Alice 選擇總和較大的那一組即可。因此直接回傳 true。
DP 解法(通用,可處理變體):dp[i][j] 表示在 piles[i..j] 範圍內,當前玩家比對手多拿的最大石頭數。轉移方程:dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1])。最終 dp[0][n-1] > 0 即 Alice 贏。
C++ 解法
複雜度分析
時間複雜度:O(1) — 數學解法直接回傳。DP 解法為 O(n^2),n 為石頭堆數。
空間複雜度:O(1) — 數學解法。DP 解法為 O(n^2)(可用滾動陣列優化到 O(n))。
虛擬碼
Mathematical approach:
1. Return true (Alice always wins)
DP approach:
1. dp[i][j] = max score difference for current player in piles[i..j]
2. Base case: dp[i][i] = piles[i]
3. For each interval length from 2 to n:
a. For each starting index i:
- j = i + length - 1
- dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1])
4. Return dp[0][n-1] > 0其他解法
區間 DP(通用解法):dp[i][j] 表示 piles[i..j] 中先手比後手多拿的石頭數。這是面試中更有價值的解法,因為它適用於堆數為奇數、不保證先手贏等變體。時間 O(n^2),空間 O(n^2),可用一維滾動陣列優化到 O(n)。
記憶化搜尋:用 (i, j) 作為狀態遞迴計算,邏輯與 DP 等價但由頂而下,更直觀。
延伸思考
- 為什麼 Alice 可以控制只拿奇數位或偶數位的石頭?詳細證明。
- 如果石頭堆數為奇數,Alice 還一定能贏嗎?
- Stone Game II、III、IV 分別加了什麼變化?DP 方程需要如何調整?