From c24910c8242da7ca5c78df8f68e6b70ef656d081 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Mon, 14 Oct 2024 16:23:22 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3320 No.3320.Count The Number of Winning Sequences --- .../README.md | 189 +++++++++++++++++- .../README_EN.md | 189 +++++++++++++++++- .../Solution.cpp | 41 ++++ .../Solution.go | 56 ++++++ .../Solution.java | 47 +++++ .../Solution.py | 27 +++ 6 files changed, 539 insertions(+), 10 deletions(-) create mode 100644 solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.cpp create mode 100644 solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.go create mode 100644 solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.java create mode 100644 solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.py diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/README.md b/solution/3300-3399/3320.Count The Number of Winning Sequences/README.md index e08afff498c5c..93c61e0a55700 100644 --- a/solution/3300-3399/3320.Count The Number of Winning Sequences/README.md +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/README.md @@ -79,32 +79,211 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3320.Co -### 方法一 +### 方法一:记忆化搜索 + +我们设计一个函数 $\textit{dfs}(i, j, k)$,其中 $i$ 表示从字符串 $s$ 的第 $i$ 个字符开始,目前 $\textit{Alice}$ 与 $\textit{Bob}$ 的分数差为 $j$,并且 $\textit{Bob}$ 上一次召唤的生物是 $k$,一共有多少种 $\textit{Bob}$ 的出招序列可以战胜 $\textit{Alice}$。 + +那么答案就是 $\textit{dfs}(0, 0, -1)$。其中 $-1$ 表示 $\textit{Bob}$ 还没有召唤过生物。在除了 $\textit{Python}$ 之外的语言中,由于分数差可能为负数,我们可以将分数差加上 $n$,这样就可以保证分数差为非负数。 + +函数 $\textit{dfs}(i, j, k)$ 的计算过程如下: + +- 如果 $n - i \leq j$,那么剩余的回合数不足以使 $\textit{Bob}$ 的分数超过 $\textit{Alice}$ 的分数,此时返回 $0$。 +- 如果 $i \geq n$,那么所有回合已经结束,如果 $\textit{Bob}$ 的分数小于 $0$,那么返回 $1$,否则返回 $0$。 +- 否则,我们枚举 $\textit{Bob}$ 这一回合召唤的生物,如果这一回合召唤的生物与上一回合召唤的生物相同,那么这一回合 $\textit{Bob}$ 无法获胜,直接跳过。否则,我们递归计算 $\textit{dfs}(i + 1, j + \textit{calc}(d[s[i]], l), l)$,其中 $\textit{calc}(x, y)$ 表示 $x$ 与 $y$ 之间的胜负关系,而 $d$ 是一个映射,将字符映射到 $\textit{012}$。我们将所有的结果相加并对 $10^9 + 7$ 取模。 + +时间复杂度 $O(n^2 \times k^2)$,其中 $n$ 是字符串 $s$ 的长度,而 $k$ 表示字符集的大小。空间复杂度 $O(n^2 \times k)$。 #### Python3 ```python - +class Solution: + def countWinningSequences(self, s: str) -> int: + def calc(x: int, y: int) -> int: + if x == y: + return 0 + if x < y: + return 1 if x == 0 and y == 2 else -1 + return -1 if x == 2 and y == 0 else 1 + + @cache + def dfs(i: int, j: int, k: int) -> int: + if len(s) - i <= j: + return 0 + if i >= len(s): + return int(j < 0) + res = 0 + for l in range(3): + if l == k: + continue + res = (res + dfs(i + 1, j + calc(d[s[i]], l), l)) % mod + return res + + mod = 10**9 + 7 + d = {"F": 0, "W": 1, "E": 2} + ans = dfs(0, 0, -1) + dfs.cache_clear() + return ans ``` #### Java ```java - +class Solution { + private int n; + private char[] s; + private int[] d = new int[26]; + private Integer[][][] f; + private final int mod = (int) 1e9 + 7; + + public int countWinningSequences(String s) { + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + this.s = s.toCharArray(); + n = this.s.length; + f = new Integer[n][n + n + 1][4]; + return dfs(0, n, 3); + } + + private int dfs(int i, int j, int k) { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != null) { + return f[i][j][k]; + } + + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + } + + private int calc(int x, int y) { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int countWinningSequences(string s) { + int n = s.size(); + int d[26]{}; + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + int f[n][n + n + 1][4]; + memset(f, -1, sizeof(f)); + auto calc = [](int x, int y) -> int { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + }; + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(dfs, i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, n, 3); + } +}; ``` #### Go ```go - +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) +} ``` diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/README_EN.md b/solution/3300-3399/3320.Count The Number of Winning Sequences/README_EN.md index 5d9d83673979d..a8aeb66e0cebb 100644 --- a/solution/3300-3399/3320.Count The Number of Winning Sequences/README_EN.md +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/README_EN.md @@ -76,32 +76,211 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3320.Co -### Solution 1 +### Solution 1: Memoization Search + +We design a function $\textit{dfs}(i, j, k)$, where $i$ represents starting from the $i$-th character of the string $s$, $j$ represents the current score difference between $\textit{Alice}$ and $\textit{Bob}$, and $k$ represents the last creature summoned by $\textit{Bob}$. The function calculates how many sequences of moves $\textit{Bob}$ can make to defeat $\textit{Alice}$. + +The answer is $\textit{dfs}(0, 0, -1)$, where $-1$ indicates that $\textit{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 $\textit{dfs}(i, j, k)$ is as follows: + +- If $n - i \leq j$, then the remaining rounds are not enough for $\textit{Bob}$ to surpass $\textit{Alice}$'s score, so return $0$. +- If $i \geq n$, then all rounds have ended. If $\textit{Bob}$'s score is less than $0$, return $1$; otherwise, return $0$. +- Otherwise, we enumerate the creatures $\textit{Bob}$ can summon this round. If the creature summoned this round is the same as the one summoned in the previous round, $\textit{Bob}$ cannot win this round, so we skip it. Otherwise, we recursively calculate $\textit{dfs}(i + 1, j + \textit{calc}(d[s[i]], l), l)$, where $\textit{calc}(x, y)$ represents the outcome between $x$ and $y$, and $d$ is a mapping that maps characters to $\textit{012}$. We sum all the results and take the modulo $10^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)$. #### Python3 ```python - +class Solution: + def countWinningSequences(self, s: str) -> int: + def calc(x: int, y: int) -> int: + if x == y: + return 0 + if x < y: + return 1 if x == 0 and y == 2 else -1 + return -1 if x == 2 and y == 0 else 1 + + @cache + def dfs(i: int, j: int, k: int) -> int: + if len(s) - i <= j: + return 0 + if i >= len(s): + return int(j < 0) + res = 0 + for l in range(3): + if l == k: + continue + res = (res + dfs(i + 1, j + calc(d[s[i]], l), l)) % mod + return res + + mod = 10**9 + 7 + d = {"F": 0, "W": 1, "E": 2} + ans = dfs(0, 0, -1) + dfs.cache_clear() + return ans ``` #### Java ```java - +class Solution { + private int n; + private char[] s; + private int[] d = new int[26]; + private Integer[][][] f; + private final int mod = (int) 1e9 + 7; + + public int countWinningSequences(String s) { + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + this.s = s.toCharArray(); + n = this.s.length; + f = new Integer[n][n + n + 1][4]; + return dfs(0, n, 3); + } + + private int dfs(int i, int j, int k) { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != null) { + return f[i][j][k]; + } + + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + } + + private int calc(int x, int y) { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int countWinningSequences(string s) { + int n = s.size(); + int d[26]{}; + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + int f[n][n + n + 1][4]; + memset(f, -1, sizeof(f)); + auto calc = [](int x, int y) -> int { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + }; + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(dfs, i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, n, 3); + } +}; ``` #### Go ```go - +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) +} ``` diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.cpp b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.cpp new file mode 100644 index 0000000000000..e438deba1d812 --- /dev/null +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.cpp @@ -0,0 +1,41 @@ +class Solution { +public: + int countWinningSequences(string s) { + int n = s.size(); + int d[26]{}; + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + int f[n][n + n + 1][4]; + memset(f, -1, sizeof(f)); + auto calc = [](int x, int y) -> int { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + }; + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(dfs, i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, n, 3); + } +}; diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.go b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.go new file mode 100644 index 0000000000000..9319af1afb6c4 --- /dev/null +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.go @@ -0,0 +1,56 @@ +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) +} diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.java b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.java new file mode 100644 index 0000000000000..64003eec7cf72 --- /dev/null +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.java @@ -0,0 +1,47 @@ +class Solution { + private int n; + private char[] s; + private int[] d = new int[26]; + private Integer[][][] f; + private final int mod = (int) 1e9 + 7; + + public int countWinningSequences(String s) { + d['W' - 'A'] = 1; + d['E' - 'A'] = 2; + this.s = s.toCharArray(); + n = this.s.length; + f = new Integer[n][n + n + 1][4]; + return dfs(0, n, 3); + } + + private int dfs(int i, int j, int k) { + if (n - i <= j - n) { + return 0; + } + if (i >= n) { + return j - n < 0 ? 1 : 0; + } + if (f[i][j][k] != null) { + return f[i][j][k]; + } + + int ans = 0; + for (int l = 0; l < 3; ++l) { + if (l == k) { + continue; + } + ans = (ans + dfs(i + 1, j + calc(d[s[i] - 'A'], l), l)) % mod; + } + return f[i][j][k] = ans; + } + + private int calc(int x, int y) { + if (x == y) { + return 0; + } + if (x < y) { + return x == 0 && y == 2 ? 1 : -1; + } + return x == 2 && y == 0 ? -1 : 1; + } +} diff --git a/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.py b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.py new file mode 100644 index 0000000000000..a64389b5dfd93 --- /dev/null +++ b/solution/3300-3399/3320.Count The Number of Winning Sequences/Solution.py @@ -0,0 +1,27 @@ +class Solution: + def countWinningSequences(self, s: str) -> int: + def calc(x: int, y: int) -> int: + if x == y: + return 0 + if x < y: + return 1 if x == 0 and y == 2 else -1 + return -1 if x == 2 and y == 0 else 1 + + @cache + def dfs(i: int, j: int, k: int) -> int: + if len(s) - i <= j: + return 0 + if i >= len(s): + return int(j < 0) + res = 0 + for l in range(3): + if l == k: + continue + res = (res + dfs(i + 1, j + calc(d[s[i]], l), l)) % mod + return res + + mod = 10**9 + 7 + d = {"F": 0, "W": 1, "E": 2} + ans = dfs(0, 0, -1) + dfs.cache_clear() + return ans