Medium
题目描述
Alice 和 Bob 用几堆石子在做游戏。一共有偶数堆石子排成一行,每堆都有正整数颗石子,数目为 piles[i]。
游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。
Alice 和 Bob 轮流进行,Alice 先开始。每回合,玩家从行的开始或结束处取走整堆石头。这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的人获胜。
假设 Alice 和 Bob 都发挥出最佳水平,当 Alice 赢得比赛时返回 true,当 Bob 赢得比赛时返回 false。
示例 1:
输入:piles = [5,3,4,5]
输出:true
解释:
Alice 先开始,只能拿前面的 5 颗或后面的 5 颗石子。
假设他取了前面的 5 颗,这样一行石子变成了 [3,4,5] 。
如果 Bob 拿走了 3,那么剩下的是 [4,5],Alice 拿走 5 赢得 10 分。
如果 Bob 拿走了后面的 5,那么剩下的是 [3,4],Alice 拿走 4 赢得 9 分。
这表明,取前面的 5 颗石子对 Alice 来说是一个胜利的举动,所以返回 true。
示例 2:
输入:piles = [3,7,2,3]
输出:true
提示:
2 <= piles.length <= 500piles.length是偶数1 <= piles[i] <= 500sum(piles[i])是奇数
解题思路
这道题有两种经典解法:
解法一:数学证明(推荐) 由于石子堆数是偶数,我们可以将所有堆按索引分为两组:偶数索引组和奇数索引组。Alice 作为先手,可以通过控制选择策略来确保自己总是能选到其中一组的所有石子。具体来说:
- 如果 Alice 第一步选择第一堆(索引0),那么 Bob 只能选择索引1或最后一个索引的堆
- 无论 Bob 怎么选,Alice 都可以继续选择偶数索引的堆
- 类似地,如果 Alice 第一步选择最后一堆,她可以控制选择奇数索引的堆
由于总石子数是奇数,偶数组和奇数组的石子数不可能相等,Alice 可以选择石子数更多的那组,因此 Alice 必胜。
解法二:动态规划
定义 dp[i][j] 表示当剩余石子堆为 piles[i...j] 时,当前玩家与另一玩家的石子数差的最大值。状态转移方程为:
dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1])
虽然动态规划解法更通用,但对于这道特定题目,数学解法更优雅。
代码实现
class Solution {
public:
bool stoneGame(vector<int>& piles) {
return true;
}
};
class Solution:
def stoneGame(self, piles: List[int]) -> bool:
return True
public class Solution {
public bool StoneGame(int[] piles) {
return true;
}
}
/**
* @param {number[]} piles
* @return {boolean}
*/
var stoneGame = function(piles) {
return true;
};
复杂度分析
| 复杂度 | 数学解法 | 动态规划解法 |
|---|---|---|
| 时间复杂度 | O(1) | O(n²) |
| 空间复杂度 | O(1) | O(n²) |
数学解法基于题目的特殊条件(偶数堆、奇数总和),直接得出 Alice 必胜的结论,是最优解法。
相关题目
. Stone Game V (Hard)
. Stone Game VI (Medium)
. Stone Game VII (Medium)
. Stone Game VIII (Hard)
. Stone Game IX (Medium)
. Strictly Palindromic Number (Medium)