Count The Number of Winning Sequences solution and explanation
8 more videos on this problem
Dynamic Programming for Leetcode | Leetcode 3320 Count The Number of Winning SequencesCF Step · 31:27 · 541 views
Leetcode 3320 Count The Number of Winning Sequences HindiThinkCode · 11:17 · 449 views
Leetcode Weekly Contest 419 | 3320. Count The Number of Winning Sequences | DP | Recursion | CodeFodCodeFod · 20:37 · 412 views
3320. Count The Number of Winning Sequences (Leetcode Hard)Programming Live with Larry · 22:16 · 383 views
3320. Count The Number of Winning Sequences || Leetcode Weekly contest 419 || #leetcodeproblem #dsaGad-An-Tik · 12:23 · 128 views
3320. Count The Number of Winning Sequences | Leetcode Weekly contest 419 | Dynamic ProgrammingDev · 20:13 · 115 views
Leetcode 3320 | Count The Number of Winning Sequences | Weekly Contest 419Road To FAANG · 10:34 · 83 views
3320. Count The Number of Winning Sequences | Leetcode | Weekly Contest 419Amit Choraria · 15:37 · 38 views
Leetcode | Weekly Contest 419 | 3320. Count The Number of Winning Sequences | SolutionCode Wanderer · 12:47 · 17 views
The problem
Alice and Bob are playing a fantasy battle game consisting of n rounds where they summon one of three magical creatures each round: a Fire Dragon, a Water Serpent, or an Earth Golem. In each round, players simultaneously summon their creature and are awarded points as follows:
- If one player summons a Fire Dragon and the other summons an Earth Golem, the player who summoned the Fire Dragon is awarded a point.
- If one player summons a Water Serpent and the other summons a Fire Dragon, the player who summoned the Water Serpent is awarded a point.
- If one player summons an Earth Golem and the other summons a Water Serpent, the player who summoned the Earth Golem is awarded a point.
- If both players summon the same creature, no player is awarded a point.
You are given a string s consisting of n characters 'F', 'W', and 'E', representing the sequence of creatures Alice will summon in each round:
- If
s[i] == 'F', Alice summons a Fire Dragon. - If
s[i] == 'W', Alice summons a Water Serpent. - If
s[i] == 'E', Alice summons an Earth Golem.
Bob’s sequence of moves is unknown, but it is guaranteed that Bob will never summon the same creature in two consecutive rounds. Bob beats Alice if the total number of points awarded to Bob after n rounds is strictly greater than the points awarded to Alice.
Return the number of distinct sequences Bob can use to beat Alice.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: s = "FFF"
Output: 3
Explanation:
Bob can beat Alice by making one of the following sequences of moves: "WFW", "FWF", or "WEW". Note that other winning sequences like "WWE" or "EWW" are invalid since Bob cannot make the same move twice in a row.
Example 2:
Input: s = "FWEFW"
Output: 18
Explanation:
Bob can beat Alice by making one of the following sequences of moves: "FWFWF", "FWFWE", "FWEFE", "FWEWE", "FEFWF", "FEFWE", "FEFEW", "FEWFE", "WFEFE", "WFEWE", "WEFWF", "WEFWE", "WEFEF", "WEFEW", "WEWFW", "WEWFE", "EWFWE", or "EWEWE".
Constraints:
1 <= s.length <= 1000s[i]is one of'F','W', or'E'.
Approach overview
Problem Overview: You are given a string representing Alice’s moves in a cyclic battle game (Fire, Water, Earth). Bob chooses his own sequence of moves but cannot repeat the same move consecutively. A move wins, loses, or draws based on the cyclic rule (F beats E, E beats W, W beats F). The task is to count how many valid sequences Bob can play so that his final score is strictly greater than Alice’s.
Approach 1: Recursive Backtracking with Memoization (O(n^2) time, O(n^2) space)
Model the game round by round. At index i, Bob chooses one of three moves except the move used in the previous round. Each choice changes the score difference depending on whether Bob wins, loses, or draws against Alice’s move. The recursive state becomes (i, lastMove, scoreDiff). Since the score difference ranges roughly from -n to +n, caching results with memoization prevents recomputation. This turns an exponential search into about O(n * 3 * 2n) states. Use recursion plus a hash/map or 3‑D DP array to store computed states.
Approach 2: Dynamic Programming (O(n^2) time, O(n^2) space)
Convert the recursion into bottom‑up dynamic programming. Track dp[i][last][diff], the number of ways after processing i rounds where Bob’s last move is last and the score difference equals diff. For each position, iterate through the three possible moves and skip the one equal to last. Compute the round outcome against Alice’s move and update the next score difference. Because the score difference may be negative, shift the index by +n when storing it. After processing all characters of the string, sum all states where the final difference is positive.
This approach works well because the number of possible score differences grows linearly with the number of rounds, keeping the state space manageable. The transitions are simple constant‑time updates, making the overall complexity about O(n^2). The DP formulation also avoids recursion overhead and is easier to optimize in Python or JavaScript.
Recommended for interviews: Start by describing the recursive state and transitions using dynamic programming. Then convert it into a bottom‑up DP table for clarity and performance. Interviewers typically expect the DP state (index, lastMove, scoreDiff) and a complexity around O(n^2). The memoized recursion shows understanding of the state space, while the iterative DP demonstrates strong implementation skills.
Approach 1: Dynamic Programming Approach
The fundamental observation is that Bob will summon sequences with the following constraints:
- He cannot summon the same creature in consecutive rounds.
- He needs to win more rounds than Alice.
We use dynamic programming to track how many ways Bob can schedule his creatures over the rounds to beat Alice.
Use a DP table dp[i][b] where i is the round number and b is the last creature Bob used. This helps to track winning sequences with the last creature being 'F', 'W', or 'E'.
MOD = 1000000007
def countWinningSequences(s):
n = len(s)
dp = [[[0] * 3 for _ in range(n)] for _ in range(3)] # 3 x n x 3
def get_index(c):
if c == 'F': return 0
if c == 'W': return 1
return 2
# Set initial possible choices for the first Bob move
for j in range(3):
if j != get_index(s[0]):
dp[get_index(s[0])][0][j] = 1
# Fill dp table
for i in range(1, n):
for a in range(3):
for b in range(3):
if b == get_index(s[i]):
continue
for c in range(3):
if c != b:
dp[get_index(s[i])][i][b] = (dp[get_index(s[i])][i][b] + dp[a][i-1][c]) % MOD
# Calculate the total winning sequences
res = 0
for a in range(3):
for b in range(3):
res = (res + dp[a][n-1][b]) % MOD
return res
# Example usage
s = "FWEFW"
print(countWinningSequences(s))const MOD = 1000000007;
function getCreatureIndex(c) {
if (c === 'F') return 0;
if (c === 'W') return 1;
return 2;
}
function countWinningSequences(s) {
let n = s.length;
let dp = Array.from({length: 3}, () => Array.from({length: n}, () => Array(3).fill(0)));
// Initialize the first round
for (let j = 0; j < 3; j++) {
if (j !== getCreatureIndex(s[0])) {
dp[getCreatureIndex(s[0])][0][j] = 1;
}
}
// Fill DP table
for (let i = 1; i < n; i++) {
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
if (b === getCreatureIndex(s[i])) continue;
for (let c = 0; c < 3; c++) {
if (c !== b) {
dp[getCreatureIndex(s[i])][i][b] = (dp[getCreatureIndex(s[i])][i][b] + dp[a][i-1][c]) % MOD;
}
}
}
}
}
// Calculate result
let res = 0;
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
res = (res + dp[a][n-1][b]) % MOD;
}
}
return res;
}
// Example usage
let s = 'FWEFW';
console.log(countWinningSequences(s));This solution uses a 3D dynamic programming table where each dimension is interpreted as:
dp[a][i][b]: Number of ways to beat Alice given last move was creaturebup to roundi.- The transitions account for changes based on Alice's moves and ensure Bob's constraints.
The result is computed by summing up all possible ways Bob can arrange his creatures to have more points than Alice.
Time Complexity: O(n) where n is the length of string s.
Space Complexity: O(n) due to the size of the DP table.
Approach 2: Recursive Backtracking with Memoization
This approach involves using a recursive function to simulate Bob's choices. We apply memoization to store results of previously calculated states to avoid redundant calculations.
The function considers the previous move and current round and checks all valid creature choices Bob can make such that he beats Alice's current round choice. We use a map to store the memoized values for states already computed.
import java.util.*;
public class WinningSequences {
private static final int MOD = 1000000007;
private static int getCreatureIndex(char c) {
return (c == 'F') ? 0 : (c == 'W') ? 1 : 2;
}
private static int backtrack(String s, int round, int lastBob, int aliceScore, int bobScore, int[][][] memo) {
if (round == s.length()) return (bobScore > aliceScore) ? 1 : 0;
if (memo[round][lastBob][bobScore > aliceScore ? 1 : 0] != -1)
return memo[round][lastBob][bobScore > aliceScore ? 1 : 0];
int res = 0;
int aliceMove = getCreatureIndex(s.charAt(round));
for (int bobMove = 0; bobMove < 3; ++bobMove) {
if (bobMove == lastBob) continue;
int newBobScore = bobScore;
if ((aliceMove == 0 && bobMove == 1) || (aliceMove == 1 && bobMove == 2) || (aliceMove == 2 && bobMove == 0)) {
++newBobScore;
}
res = (res + backtrack(s, round + 1, bobMove, aliceScore + (bobMove == aliceMove ? 0 : 1), newBobScore, memo)) % MOD;
}
return memo[round][lastBob][bobScore > aliceScore ? 1 : 0] = res;
}
public static int countWinningSequences(String s) {
int[][][] memo = new int[s.length()][3][2];
for (int[][] mat : memo) for (int[] row : mat) Arrays.fill(row, -1);
return backtrack(s, 0, -1, 0, 0, memo);
}
public static void main(String[] args) {
String s = "FWEFW";
System.out.println(countWinningSequences(s));
}
}#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int MOD = 1000000007;
int getCreatureIndex(char c) {
if (c == 'F') return 0;
if (c == 'W') return 1;
return 2;
}
int backtrack(string &s, int round, int lastBob, int aliceScore, int bobScore, vector<vector<vector<int>>> &memo) {
if (round == s.size()) return bobScore > aliceScore ? 1 : 0;
if (memo[round][lastBob][bobScore > aliceScore ? 1 : 0] != -1)
return memo[round][lastBob][bobScore > aliceScore ? 1 : 0];
int res = 0;
int aliceMove = getCreatureIndex(s[round]);
for (int bobMove = 0; bobMove < 3; ++bobMove) {
if (bobMove == lastBob) continue;
int newBobScore = bobScore;
if ((aliceMove == 0 && bobMove == 1) || (aliceMove == 1 && bobMove == 2) || (aliceMove == 2 && bobMove == 0)) {
++newBobScore;
}
res = (res + backtrack(s, round + 1, bobMove, aliceScore + (bobMove == aliceMove ? 0 : 1), newBobScore, memo)) % MOD;
}
return memo[round][lastBob][bobScore > aliceScore ? 1 : 0] = res;
}
int countWinningSequences(string s) {
vector<vector<vector<int>>> memo(s.size(), vector<vector<int>>(3, vector<int>(2, -1)));
return backtrack(s, 0, -1, 0, 0, memo);
}
int main() {
string s = "FWEFW";
cout << countWinningSequences(s) << endl;
return 0;
}This Java solution implements the recursive backtracking method with memoization to prevent redundant computations. It evaluates potential paths for Bob to pick his creatures against Alice's sequence, ensuring non-consecutive choices and maximizing Bob’s score.
Time Complexity: O(n * 3^2), acquisitions of successive moves restrict the state exploration.
Space Complexity: O(n * 3 * 2) due to memoization.
Approach 3: Memoization Search
We design a function dfs(i, j, k), where i represents starting from the i-th character of the string s, j represents the current score difference between Alice and Bob, and k represents the last creature summoned by Bob. The function calculates how many sequences of moves Bob can make to defeat Alice.
The answer is dfs(0, 0, -1), where -1 indicates that Bob has not summoned any creatures yet. In languages other than Python, since the score difference can be negative, we can add n to the score difference to ensure it is non-negative.
The calculation process of the function dfs(i, j, k) is as follows:
- If
n - i leq j, then the remaining rounds are not enough forBobto surpassAlice's score, so return0. - If
i geq n, then all rounds have ended. IfBob's score is less than0, return1; otherwise, return0. - Otherwise, we enumerate the creatures
Bobcan summon this round. If the creature summoned this round is the same as the one summoned in the previous round,Bobcannot win this round, so we skip it. Otherwise, we recursively calculatedfs(i + 1, j + calc(d[s[i]], l), l), wherecalc(x, y)represents the outcome betweenxandy, anddis a mapping that maps characters to012. We sum all the results and take the modulo10^9 + 7.
The time complexity is O(n^2 times k^2), where n is the length of the string s, and k represents the size of the character set. The space complexity is O(n^2 times k).
func countWinningSequences(s string) int {
const mod int = 1e9 + 7
d := [26]int{}
d['W'-'A'] = 1
d['E'-'A'] = 2
n := len(s)
f := make([][][4]int, n)
for i := range f {
f[i] = make([][4]int, n+n+1)
for j := range f[i] {
for k := range f[i][j] {
f[i][j][k] = -1
}
}
}
calc := func(x, y int) int {
if x == y {
return 0
}
if x < y {
if x == 0 && y == 2 {
return 1
}
return -1
}
if x == 2 && y == 0 {
return -1
}
return 1
}
var dfs func(int, int, int) int
dfs = func(i, j, k int) int {
if n-i <= j-n {
return 0
}
if i >= n {
if j-n < 0 {
return 1
}
return 0
}
if v := f[i][j][k]; v != -1 {
return v
}
ans := 0
for l := 0; l < 3; l++ {
if l == k {
continue
}
ans = (ans + dfs(i+1, j+calc(d[s[i]-'A'], l), l)) % mod
}
f[i][j][k] = ans
return ans
}
return dfs(0, n, 3)
}Complexity comparison
| Approach | Complexity |
|---|---|
| Dynamic Programming Approach | Time Complexity: |
| Recursive Backtracking with Memoization | Time Complexity: |
| Memoization Search | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Recursive Backtracking with Memoization | O(n^2) | O(n^2) | When deriving the solution from game simulation and exploring the state space naturally with recursion. |
| Dynamic Programming (Score Difference DP) | O(n^2) | O(n^2) | Best general solution. Efficient for n up to typical constraints and avoids recursion overhead. |
Frequently asked questions
Is Count The Number of Winning Sequences easy or hard?
Count The Number of Winning Sequences is classified as a Hard problem. The difficulty comes from modeling the cyclic win/lose rules, preventing consecutive moves, and tracking score differences across all rounds using dynamic programming.
Count The Number of Winning Sequences Python/Java solution
Python and Java implementations typically use dynamic programming or recursion with memoization. The state tracks the current index, the last move played by Bob, and the score difference relative to Alice. The algorithm iterates through possible moves while preventing consecutive duplicates and accumulates valid winning sequences.
How to solve Count The Number of Winning Sequences in O(n)?
An O(n) solution is generally not feasible because the score difference can vary across roughly 2n possible values at each step. The standard solution tracks these differences using dynamic programming, leading to O(n^2) time complexity. Attempts to compress the state still require iterating over possible score differences.
What is the best approach for Count The Number of Winning Sequences?
The most effective approach uses dynamic programming with state (index, lastMove, scoreDifference). For each round you try the three possible moves except the previous one and update the score difference depending on the game outcome. This reduces the search space to about O(n^2) states and efficiently counts all valid winning sequences.
Is Count The Number of Winning Sequences asked at Google/Amazon/Meta?
Hard dynamic programming problems involving game states and score differences are common in interviews at companies like Google, Amazon, and Meta. While this exact problem may not always appear, the pattern of modeling game outcomes with DP states is frequently tested.
What data structure is used in Count The Number of Winning Sequences?
The core data structure is a dynamic programming table or memoization cache storing states defined by index, last move, and score difference. Arrays or hash maps are commonly used depending on the language implementation.
What is the time complexity of Count The Number of Winning Sequences?
The optimal dynamic programming solution runs in O(n^2) time. The algorithm tracks states for each position, the previous move (3 possibilities), and the score difference ranging from about -n to +n. Space complexity is also O(n^2) due to the DP table storing these states.
