Skip to content

Commit 7187d92

Browse files
authored
feat: add solutions to lc problem: No.0837 (#4649)
No.0837.New 21 Game
1 parent 30b7bfe commit 7187d92

File tree

5 files changed

+113
-27
lines changed

5 files changed

+113
-27
lines changed

solution/0800-0899/0837.New 21 Game/README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,57 +75,57 @@ tags:
7575
函数 $dfs(i)$ 的计算方法如下:
7676

7777
- 如果 $i \ge k$,那么停止抽取数字,如果 $i \le n$,返回 $1$,否则返回 $0$;
78-
- 否则,可以在 $[1,..maxPts]$ 范围内抽取下一个数字 $j$,那么 $dfs(i) = \frac{1}{maxPts} \sum_{j=1}^{maxPts} dfs(i+j)$。
78+
- 否则,可以在 $[1,..\textit{maxPts}]$ 范围内抽取下一个数字 $j$,那么 $dfs(i) = \frac{1}{maxPts} \sum_{j=1}^{maxPts} dfs(i+j)$。
7979

8080
这里我们可以使用记忆化搜索来加速计算。
8181

82-
以上方法的时间复杂度为 $O(k \times maxPts)$,会超出时间限制,我们需要优化一下。
82+
以上方法的时间复杂度为 $O(k \times \textit{maxPts})$,会超出时间限制,我们需要优化一下。
8383

8484
当 $i \lt k$ 时,以下等式成立:
8585

8686
$$
8787
\begin{aligned}
88-
dfs(i) &= (dfs(i + 1) + dfs(i + 2) + \cdots + dfs(i + maxPts)) / maxPts & (1)
88+
dfs(i) &= (dfs(i + 1) + dfs(i + 2) + \cdots + dfs(i + \textit{maxPts})) / \ & (1)
8989
\end{aligned}
9090
$$
9191

9292
当 $i \lt k - 1$ 时,以下等式成立:
9393

9494
$$
9595
\begin{aligned}
96-
dfs(i+1) &= (dfs(i + 2) + dfs(i + 3) + \cdots + dfs(i + maxPts + 1)) / maxPts & (2)
96+
dfs(i+1) &= (dfs(i + 2) + dfs(i + 3) + \cdots + dfs(i + \textit{maxPts} + 1)) / \textit{maxPts} & (2)
9797
\end{aligned}
9898
$$
9999

100100
因此,当 $i \lt k-1$ 时,我们将等式 $(1)$ 减去等式 $(2)$,得到:
101101

102102
$$
103103
\begin{aligned}
104-
dfs(i) - dfs(i+1) &= (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts
104+
dfs(i) - dfs(i+1) &= (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}
105105
\end{aligned}
106106
$$
107107

108108
即:
109109

110110
$$
111111
\begin{aligned}
112-
dfs(i) &= dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts
112+
dfs(i) &= dfs(i + 1) + (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}
113113
\end{aligned}
114114
$$
115115

116116
如果 $i=k-1$,有:
117117

118118
$$
119119
\begin{aligned}
120-
dfs(i) &= dfs(k - 1) &= dfs(k) + dfs(k + 1) + \cdots + dfs(k + maxPts - 1) / maxPts & (3)
120+
dfs(i) &= dfs(k - 1) &= dfs(k) + dfs(k + 1) + \cdots + dfs(k + \textit{maxPts} - 1) / \textit{maxPts} & (3)
121121
\end{aligned}
122122
$$
123123

124-
我们假设有 $i$ 个数不超过 $n$,那么 $k+i-1 \leq n$,又因为 $i\leq maxPts$,所以 $i \leq \min(n-k+1, maxPts)$,因此等式 $(3)$ 可以写成:
124+
我们假设有 $i$ 个数不超过 $n$,那么 $k+i-1 \leq n$,又因为 $i\leq \textit{maxPts}$,所以 $i \leq \min(n-k+1, \textit{maxPts})$,因此等式 $(3)$ 可以写成:
125125

126126
$$
127127
\begin{aligned}
128-
dfs(k-1) &= \min(n-k+1, maxPts) / maxPts
128+
dfs(k-1) &= \min(n-k+1, \textit{maxPts}) / \textit{maxPts}
129129
\end{aligned}
130130
$$
131131

@@ -136,13 +136,13 @@ $$
136136
dfs(i) &= \begin{cases}
137137
1, & i \geq k, i \leq n \\
138138
0, & i \geq k, i \gt n \\
139-
\min(n-k+1, maxPts) / maxPts, & i = k - 1 \\
140-
dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts, & i < k - 1
139+
\min(n-k+1, \textit{maxPts}) / \textit{maxPts}, & i = k - 1 \\
140+
dfs(i + 1) + (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}, & i < k - 1
141141
\end{cases}
142142
\end{aligned}
143143
$$
144144

145-
时间复杂度 $O(k + maxPts)$,空间复杂度 $O(k + maxPts)$。其中 $k$ 为最大分数。
145+
时间复杂度 $O(k + \textit{maxPts})$,空间复杂度 $O(k + \textit{maxPts})$。其中 $k$ 为最大分数。
146146

147147
<!-- tabs:start -->
148148

@@ -246,7 +246,7 @@ func new21Game(n int, k int, maxPts int) float64 {
246246

247247
```ts
248248
function new21Game(n: number, k: number, maxPts: number): number {
249-
const f = new Array(k).fill(0);
249+
const f: number[] = Array(k).fill(0);
250250
const dfs = (i: number): number => {
251251
if (i >= k) {
252252
return i <= n ? 1 : 0;
@@ -275,13 +275,13 @@ function new21Game(n: number, k: number, maxPts: number): number {
275275

276276
定义 $f[i]$ 表示当前分数为 $i$ 时,到最终停止抽取数字时,分数不超过 $n$ 的概率。那么答案就是 $f[0]$。
277277

278-
当 $k \leq i \leq \min(n, k + maxPts - 1)$ 时,有 $f[i] = 1$。
278+
当 $k \leq i \leq \min(n, k + \textit{maxPts} - 1)$ 时,有 $f[i] = 1$。
279279

280-
当 $i = k - 1$ 时,有 $f[i] = \min(n-k+1, maxPts) / maxPts$。
280+
当 $i = k - 1$ 时,有 $f[i] = \min(n-k+1, \textit{maxPts}) / \textit{maxPts}$。
281281

282-
当 $i \lt k - 1$ 时,有 $f[i] = f[i + 1] + (f[i + 1] - f[i + maxPts + 1]) / maxPts$。
282+
当 $i \lt k - 1$ 时,有 $f[i] = f[i + 1] + (f[i + 1] - f[i + \textit{maxPts} + 1]) / \textit{maxPts}$。
283283

284-
时间复杂度 $O(k + maxPts)$,空间复杂度 $O(k + maxPts)$。其中 $k$ 为最大分数。
284+
时间复杂度 $O(k + \textit{maxPts})$,空间复杂度 $O(k + \textit{maxPts})$。其中 $k$ 为最大分数。
285285

286286
<!-- tabs:start -->
287287

@@ -369,7 +369,7 @@ function new21Game(n: number, k: number, maxPts: number): number {
369369
if (k === 0) {
370370
return 1;
371371
}
372-
const f = new Array(k + maxPts).fill(0);
372+
const f: number[] = Array(k + maxPts).fill(0);
373373
for (let i = k; i < Math.min(n + 1, k + maxPts); ++i) {
374374
f[i] = 1;
375375
}

solution/0800-0899/0837.New 21 Game/README_EN.md

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,81 @@ In 6 out of 10 possibilities, she is at or below 6 points.
6868

6969
<!-- solution:start -->
7070

71-
### Solution 1
71+
### Solution 1: Memoized Search
72+
73+
We design a function $dfs(i)$, which represents the probability that when the current score is $i$, the final score does not exceed $n$ when we stop drawing numbers. The answer is $dfs(0)$.
74+
75+
The calculation method of function $dfs(i)$ is as follows:
76+
77+
- If $i \ge k$, then we stop drawing numbers. If $i \le n$, return $1$, otherwise return $0$;
78+
- Otherwise, we can draw the next number $j$ in the range $[1,..\textit{maxPts}]$, then $dfs(i) = \frac{1}{maxPts} \sum_{j=1}^{maxPts} dfs(i+j)$.
79+
80+
Here we can use memoized search to accelerate the calculation.
81+
82+
The time complexity of the above method is $O(k \times \textit{maxPts})$, which will exceed the time limit, so we need to optimize it.
83+
84+
When $i \lt k$, the following equation holds:
85+
86+
$$
87+
\begin{aligned}
88+
dfs(i) &= (dfs(i + 1) + dfs(i + 2) + \cdots + dfs(i + \textit{maxPts})) / \textit{maxPts} & (1)
89+
\end{aligned}
90+
$$
91+
92+
When $i \lt k - 1$, the following equation holds:
93+
94+
$$
95+
\begin{aligned}
96+
dfs(i+1) &= (dfs(i + 2) + dfs(i + 3) + \cdots + dfs(i + \textit{maxPts} + 1)) / \textit{maxPts} & (2)
97+
\end{aligned}
98+
$$
99+
100+
Therefore, when $i \lt k-1$, we subtract equation $(2)$ from equation $(1)$ to get:
101+
102+
$$
103+
\begin{aligned}
104+
dfs(i) - dfs(i+1) &= (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}
105+
\end{aligned}
106+
$$
107+
108+
That is:
109+
110+
$$
111+
\begin{aligned}
112+
dfs(i) &= dfs(i + 1) + (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}
113+
\end{aligned}
114+
$$
115+
116+
If $i=k-1$, we have:
117+
118+
$$
119+
\begin{aligned}
120+
dfs(i) &= dfs(k - 1) = (dfs(k) + dfs(k + 1) + \cdots + dfs(k + \textit{maxPts} - 1)) / \textit{maxPts} & (3)
121+
\end{aligned}
122+
$$
123+
124+
We assume there are $i$ numbers not exceeding $n$, then $k+i-1 \leq n$, and since $i\leq \textit{maxPts}$, we have $i \leq \min(n-k+1, \textit{maxPts})$, so equation $(3)$ can be written as:
125+
126+
$$
127+
\begin{aligned}
128+
dfs(k-1) &= \min(n-k+1, \textit{maxPts}) / \textit{maxPts}
129+
\end{aligned}
130+
$$
131+
132+
In summary, we have the following state transition equation:
133+
134+
$$
135+
\begin{aligned}
136+
dfs(i) &= \begin{cases}
137+
1, & i \geq k, i \leq n \\
138+
0, & i \geq k, i \gt n \\
139+
\min(n-k+1, \textit{maxPts}) / \textit{maxPts}, & i = k - 1 \\
140+
dfs(i + 1) + (dfs(i + 1) - dfs(i + \textit{maxPts} + 1)) / \textit{maxPts}, & i < k - 1
141+
\end{cases}
142+
\end{aligned}
143+
$$
144+
145+
Time complexity $O(k + \textit{maxPts})$, space complexity $O(k + \textit{maxPts})$. Where $k$ is the maximum score.
72146

73147
<!-- tabs:start -->
74148

@@ -125,7 +199,7 @@ class Solution {
125199
public:
126200
double new21Game(int n, int k, int maxPts) {
127201
vector<double> f(k);
128-
function<double(int)> dfs = [&](int i) -> double {
202+
auto dfs = [&](this auto&& dfs, int i) -> double {
129203
if (i >= k) {
130204
return i <= n ? 1 : 0;
131205
}
@@ -172,7 +246,7 @@ func new21Game(n int, k int, maxPts int) float64 {
172246

173247
```ts
174248
function new21Game(n: number, k: number, maxPts: number): number {
175-
const f = new Array(k).fill(0);
249+
const f: number[] = Array(k).fill(0);
176250
const dfs = (i: number): number => {
177251
if (i >= k) {
178252
return i <= n ? 1 : 0;
@@ -195,7 +269,19 @@ function new21Game(n: number, k: number, maxPts: number): number {
195269

196270
<!-- solution:start -->
197271

198-
### Solution 2
272+
### Solution 2: Dynamic Programming
273+
274+
We can convert the memoized search in Solution 1 into dynamic programming.
275+
276+
Define $f[i]$ to represent the probability that when the current score is $i$, the final score does not exceed $n$ when we stop drawing numbers. The answer is $f[0]$.
277+
278+
When $k \leq i \leq \min(n, k + \textit{maxPts} - 1)$, we have $f[i] = 1$.
279+
280+
When $i = k - 1$, we have $f[i] = \min(n-k+1, \textit{maxPts}) / \textit{maxPts}$.
281+
282+
When $i \lt k - 1$, we have $f[i] = f[i + 1] + (f[i + 1] - f[i + \textit{maxPts} + 1]) / \textit{maxPts}$.
283+
284+
Time complexity $O(k + \textit{maxPts})$, space complexity $O(k + \textit{maxPts})$. Where $k$ is the maximum score.
199285

200286
<!-- tabs:start -->
201287

@@ -283,7 +369,7 @@ function new21Game(n: number, k: number, maxPts: number): number {
283369
if (k === 0) {
284370
return 1;
285371
}
286-
const f = new Array(k + maxPts).fill(0);
372+
const f: number[] = Array(k + maxPts).fill(0);
287373
for (let i = k; i < Math.min(n + 1, k + maxPts); ++i) {
288374
f[i] = 1;
289375
}

solution/0800-0899/0837.New 21 Game/Solution.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class Solution {
22
public:
33
double new21Game(int n, int k, int maxPts) {
44
vector<double> f(k);
5-
function<double(int)> dfs = [&](int i) -> double {
5+
auto dfs = [&](this auto&& dfs, int i) -> double {
66
if (i >= k) {
77
return i <= n ? 1 : 0;
88
}
@@ -16,4 +16,4 @@ class Solution {
1616
};
1717
return dfs(0);
1818
}
19-
};
19+
};

solution/0800-0899/0837.New 21 Game/Solution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
function new21Game(n: number, k: number, maxPts: number): number {
2-
const f = new Array(k).fill(0);
2+
const f: number[] = Array(k).fill(0);
33
const dfs = (i: number): number => {
44
if (i >= k) {
55
return i <= n ? 1 : 0;

solution/0800-0899/0837.New 21 Game/Solution2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ function new21Game(n: number, k: number, maxPts: number): number {
22
if (k === 0) {
33
return 1;
44
}
5-
const f = new Array(k + maxPts).fill(0);
5+
const f: number[] = Array(k + maxPts).fill(0);
66
for (let i = k; i < Math.min(n + 1, k + maxPts); ++i) {
77
f[i] = 1;
88
}

0 commit comments

Comments
 (0)