LeetCode 2660: Determine the Winner of a Bowling Game (Previous Two Strikes Double Rule)
LeetCode 2660ArraySimulationToday we solve LeetCode 2660 - Determine the Winner of a Bowling Game.
Source: https://leetcode.com/problems/determine-the-winner-of-a-bowling-game/
English
Problem Summary
You are given two arrays player1 and player2, where each value is the number of pins knocked down in that round. If a player scored 10 in either of the previous two rounds, the current round score is doubled. Return 1 if player 1 wins, 2 if player 2 wins, or 0 for a tie.
Key Insight
The rule only depends on a local window: for round i, check whether i-1 or i-2 was a strike (10). So we can compute each player's total in one linear pass.
Algorithm
- Write a helper score(nums).
- For each index i, set multiplier to 2 if (i >= 1 and nums[i-1] == 10) or (i >= 2 and nums[i-2] == 10), else 1.
- Add multiplier * nums[i] into total.
- Compare two totals and return 1 / 2 / 0.
Complexity Analysis
Let n be the number of rounds.
Time: O(n) per player, so O(n) overall.
Space: O(1).
Common Pitfalls
- Forgetting boundary checks for i-1 and i-2.
- Requiring both previous rounds to be strike (wrong); actually either one is enough.
- Accidentally doubling future rounds repeatedly due to state bugs instead of direct index checks.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
private int score(int[] nums) {
int total = 0;
for (int i = 0; i < nums.length; i++) {
boolean doubled = (i >= 1 && nums[i - 1] == 10) || (i >= 2 && nums[i - 2] == 10);
total += doubled ? nums[i] * 2 : nums[i];
}
return total;
}
public int isWinner(int[] player1, int[] player2) {
int s1 = score(player1);
int s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
}
}func score(nums []int) int {
total := 0
for i := 0; i < len(nums); i++ {
doubled := (i >= 1 && nums[i-1] == 10) || (i >= 2 && nums[i-2] == 10)
if doubled {
total += 2 * nums[i]
} else {
total += nums[i]
}
}
return total
}
func isWinner(player1 []int, player2 []int) int {
s1, s2 := score(player1), score(player2)
if s1 > s2 {
return 1
}
if s2 > s1 {
return 2
}
return 0
}class Solution {
public:
int score(vector<int>& nums) {
int total = 0;
for (int i = 0; i < (int)nums.size(); i++) {
bool doubled = (i >= 1 && nums[i - 1] == 10) || (i >= 2 && nums[i - 2] == 10);
total += doubled ? 2 * nums[i] : nums[i];
}
return total;
}
int isWinner(vector<int>& player1, vector<int>& player2) {
int s1 = score(player1), s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
}
};class Solution:
def _score(self, nums: List[int]) -> int:
total = 0
for i, x in enumerate(nums):
doubled = (i >= 1 and nums[i - 1] == 10) or (i >= 2 and nums[i - 2] == 10)
total += 2 * x if doubled else x
return total
def isWinner(self, player1: List[int], player2: List[int]) -> int:
s1, s2 = self._score(player1), self._score(player2)
if s1 > s2:
return 1
if s2 > s1:
return 2
return 0const score = (nums) => {
let total = 0;
for (let i = 0; i < nums.length; i++) {
const doubled = (i >= 1 && nums[i - 1] === 10) || (i >= 2 && nums[i - 2] === 10);
total += doubled ? 2 * nums[i] : nums[i];
}
return total;
};
var isWinner = function(player1, player2) {
const s1 = score(player1);
const s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
};中文
题目概述
给定两个数组 player1、player2,表示每回合击倒瓶数。若某回合前两回合中任意一回合击倒了 10,该回合分数翻倍。返回:玩家1赢为 1,玩家2赢为 2,平局为 0。
核心思路
每一回合是否翻倍只与最近两回合有关,是一个固定窗口判断问题。直接线性扫描并按规则累计即可。
算法步骤
- 写一个 score(nums) 计算单个玩家总分。
- 对每个下标 i,若 i-1 或 i-2 位置是 10,则本轮乘 2,否则乘 1。
- 累加后得到总分。
- 比较两位玩家总分并返回 1 / 2 / 0。
复杂度分析
设回合数为 n。
时间复杂度:O(n)。
空间复杂度:O(1)。
常见陷阱
- 忘记处理前两项的边界判断。
- 误写成“前两回合都要是 10 才翻倍”,其实只要任意一个是 10 即可。
- 用状态变量传播翻倍,结果影响了不该影响的回合;直接按下标判断最稳妥。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
private int score(int[] nums) {
int total = 0;
for (int i = 0; i < nums.length; i++) {
boolean doubled = (i >= 1 && nums[i - 1] == 10) || (i >= 2 && nums[i - 2] == 10);
total += doubled ? nums[i] * 2 : nums[i];
}
return total;
}
public int isWinner(int[] player1, int[] player2) {
int s1 = score(player1);
int s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
}
}func score(nums []int) int {
total := 0
for i := 0; i < len(nums); i++ {
doubled := (i >= 1 && nums[i-1] == 10) || (i >= 2 && nums[i-2] == 10)
if doubled {
total += 2 * nums[i]
} else {
total += nums[i]
}
}
return total
}
func isWinner(player1 []int, player2 []int) int {
s1, s2 := score(player1), score(player2)
if s1 > s2 {
return 1
}
if s2 > s1 {
return 2
}
return 0
}class Solution {
public:
int score(vector<int>& nums) {
int total = 0;
for (int i = 0; i < (int)nums.size(); i++) {
bool doubled = (i >= 1 && nums[i - 1] == 10) || (i >= 2 && nums[i - 2] == 10);
total += doubled ? 2 * nums[i] : nums[i];
}
return total;
}
int isWinner(vector<int>& player1, vector<int>& player2) {
int s1 = score(player1), s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
}
};class Solution:
def _score(self, nums: List[int]) -> int:
total = 0
for i, x in enumerate(nums):
doubled = (i >= 1 and nums[i - 1] == 10) or (i >= 2 and nums[i - 2] == 10)
total += 2 * x if doubled else x
return total
def isWinner(self, player1: List[int], player2: List[int]) -> int:
s1, s2 = self._score(player1), self._score(player2)
if s1 > s2:
return 1
if s2 > s1:
return 2
return 0const score = (nums) => {
let total = 0;
for (let i = 0; i < nums.length; i++) {
const doubled = (i >= 1 && nums[i - 1] === 10) || (i >= 2 && nums[i - 2] === 10);
total += doubled ? 2 * nums[i] : nums[i];
}
return total;
};
var isWinner = function(player1, player2) {
const s1 = score(player1);
const s2 = score(player2);
if (s1 > s2) return 1;
if (s2 > s1) return 2;
return 0;
};
Comments