Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d6f1bbc

Browse files
Merge pull request SharingSource#217 from SharingSource/ac_oier
✨feat: Add 375
2 parents 61f0f4b + aad5349 commit d6f1bbc

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

‎Index/区间 DP.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
| 题目 | 题解 | 难度 | 推荐指数 |
22
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
33
| [87. 扰乱字符串](https://leetcode-cn.com/problems/scramble-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/scramble-string/solution/gong-shui-san-xie-yi-ti-san-jie-di-gui-j-hybk/) | 困难 | 🤩🤩🤩 |
4+
| [375. 猜数字大小 II](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/solution/gong-shui-san-xie-yi-ti-shuang-jie-ji-yi-92e5/) | 中等 | 🤩🤩🤩🤩🤩 |
45
| [516. 最长回文子序列](https://leetcode-cn.com/problems/longest-palindromic-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/longest-palindromic-subsequence/solution/gong-shui-san-xie-qu-jian-dp-qiu-jie-zui-h2ya/) | 困难 | 🤩🤩🤩 |
56
| [664. 奇怪的打印机](https://leetcode-cn.com/problems/strange-printer/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/strange-printer/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-xqeo9/) | 中等 | 🤩🤩🤩🤩🤩 |
67
| [877. 石子游戏](https://leetcode-cn.com/problems/stone-game/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/stone-game/solution/gong-shui-san-xie-jing-dian-qu-jian-dp-j-wn31/) | 中等 | 🤩🤩🤩🤩 |

‎Index/记忆化搜索.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
| 题目 | 题解 | 难度 | 推荐指数 |
22
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
33
| [87. 扰乱字符串](https://leetcode-cn.com/problems/scramble-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/scramble-string/solution/gong-shui-san-xie-yi-ti-san-jie-di-gui-j-hybk/) | 困难 | 🤩🤩🤩 |
4+
| [375. 猜数字大小 II](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/solution/gong-shui-san-xie-yi-ti-shuang-jie-ji-yi-92e5/) | 中等 | 🤩🤩🤩🤩🤩 |
45
| [403. 青蛙过河](https://leetcode-cn.com/problems/frog-jump/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/frog-jump/solution/gong-shui-san-xie-yi-ti-duo-jie-jiang-di-74fw/) | 困难 | 🤩🤩🤩🤩 |
56
| [494. 目标和](https://leetcode-cn.com/problems/target-sum/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/target-sum/solution/gong-shui-san-xie-yi-ti-si-jie-dfs-ji-yi-et5b/) | 中等 | 🤩🤩🤩🤩 |
67
| [552. 学生出勤记录 II](https://leetcode-cn.com/problems/student-attendance-record-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/student-attendance-record-ii/solution/gong-shui-san-xie-yi-ti-san-jie-ji-yi-hu-fdfx/) | 困难 | 🤩🤩🤩🤩 |
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[375. 猜数字大小 II](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/solution/gong-shui-san-xie-yi-ti-shuang-jie-ji-yi-92e5/)** ,难度为 **中等**
4+
5+
Tag : 「博弈论」、「区间 DP」、「记忆化搜索」
6+
7+
8+
9+
我们正在玩一个猜数游戏,游戏规则如下:
10+
1. 我从 `1``n` 之间选择一个数字。
11+
2. 你来猜我选了哪个数字。
12+
3. 如果你猜到正确的数字,就会 赢得游戏 。
13+
4. 如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
14+
5. 每当你猜了数字 `x` 并且猜错了的时候,你需要支付金额为 `x` 的现金。如果你花光了钱,就会 输掉游戏 。
15+
16+
给你一个特定的数字 `n` ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。
17+
18+
19+
20+
示例 1:
21+
![](https://assets.leetcode.com/uploads/2020/09/10/graph.png)
22+
23+
```
24+
输入:n = 10
25+
26+
输出:16
27+
28+
解释:制胜策略如下:
29+
- 数字范围是 [1,10] 。你先猜测数字为 7 。
30+
- 如果这是我选中的数字,你的总费用为 0ドル 。否则,你需要支付 7ドル 。
31+
- 如果我的数字更大,则下一步需要猜测的数字范围是 [8,10] 。你可以猜测数字为 9 。
32+
- 如果这是我选中的数字,你的总费用为 7ドル 。否则,你需要支付 9ドル 。
33+
- 如果我的数字更大,那么这个数字一定是 10 。你猜测数字为 10 并赢得游戏,总费用为 7ドル + 9ドル = 16ドル 。
34+
- 如果我的数字更小,那么这个数字一定是 8 。你猜测数字为 8 并赢得游戏,总费用为 7ドル + 9ドル = 16ドル 。
35+
- 如果我的数字更小,则下一步需要猜测的数字范围是 [1,6] 。你可以猜测数字为 3 。
36+
- 如果这是我选中的数字,你的总费用为 7ドル 。否则,你需要支付 3ドル 。
37+
- 如果我的数字更大,则下一步需要猜测的数字范围是 [4,6] 。你可以猜测数字为 5 。
38+
- 如果这是我选中的数字,你的总费用为 7ドル + 3ドル = 10ドル 。否则,你需要支付 5ドル 。
39+
- 如果我的数字更大,那么这个数字一定是 6 。你猜测数字为 6 并赢得游戏,总费用为 7ドル + 3ドル + 5ドル = 15ドル 。
40+
- 如果我的数字更小,那么这个数字一定是 4 。你猜测数字为 4 并赢得游戏,总费用为 7ドル + 3ドル + 5ドル = 15ドル 。
41+
- 如果我的数字更小,则下一步需要猜测的数字范围是 [1,2] 。你可以猜测数字为 1 。
42+
- 如果这是我选中的数字,你的总费用为 7ドル + 3ドル = 10ドル 。否则,你需要支付 1ドル 。
43+
- 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 7ドル + 3ドル + 1ドル = 11ドル 。
44+
在最糟糕的情况下,你需要支付 16ドル 。因此,你只需要 16ドル 就可以确保自己赢得游戏。
45+
```
46+
示例 2:
47+
```
48+
输入:n = 1
49+
50+
输出:0
51+
52+
解释:只有一个可能的数字,所以你可以直接猜 1 并赢得游戏,无需支付任何费用。
53+
```
54+
示例 3:
55+
```
56+
输入:n = 2
57+
58+
输出:1
59+
60+
解释:有两个可能的数字 1 和 2 。
61+
- 你可以先猜 1 。
62+
- 如果这是我选中的数字,你的总费用为 0ドル 。否则,你需要支付 1ドル 。
63+
- 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 1ドル 。
64+
最糟糕的情况下,你需要支付 1ドル 。
65+
```
66+
67+
提示:
68+
* 1 <= n <= 200
69+
70+
---
71+
72+
### 基本分析
73+
74+
这不是一道可通过「二分」求解的题目,主要原因为每次惩罚的金额不固定,最小惩罚次数不等同于猜中数字的最小成本。
75+
76+
---
77+
78+
### 记忆化搜索
79+
80+
比较容易想到的做法为使用「递归」进行求解。
81+
82+
设计递归函数为 `int dfs(int l, int r)` 传入参数 `l``r` 代表在范围 $[l, r]$ 内进行猜数,返回值为在 $[l, r]$ 内猜中数字至少需要多少钱。
83+
84+
**我们可决策的部分为「选择猜哪个数 $x$」,而不可决策的是「选择某个数 $x$ 之后(假设没有猜中),真实值在落在哪边」。**
85+
86+
因而为求得「最坏情况下最好」的结果,我们应当取所有的 $x$ 中的最小值。
87+
88+
最后,为减少重复计算,我们需要在「递归」基础上加入记忆化搜索。
89+
90+
代码:
91+
```Java
92+
class Solution {
93+
int N = 210;
94+
int[][] cache = new int[N][N];
95+
public int getMoneyAmount(int n) {
96+
return dfs(1, n);
97+
}
98+
int dfs(int l, int r) {
99+
if (l >= r) return 0;
100+
if (cache[l][r] != 0) return cache[l][r];
101+
int ans = 0x3f3f3f3f;
102+
for (int x = l; x <= r; x++) {
103+
// 当选择的数位 x 时,至少需要 cur 才能猜中数字
104+
int cur = Math.max(dfs(l, x - 1), dfs(x + 1, r)) + x;
105+
// 在所有我们可以决策的数值之间取最优
106+
ans = Math.min(ans, cur);
107+
}
108+
cache[l][r] = ans;
109+
return ans;
110+
}
111+
}
112+
```
113+
* 时间复杂度:$O(n^3)$
114+
* 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(n^2)$
115+
116+
---
117+
118+
### 区间 DP
119+
120+
同样能够通过「递推」来进行求解。
121+
122+
**通过「记忆化搜索」的递归过程,我们发现,在求解 $[l, r]$ 的最小成本时,需要依赖于 $[l, i - 1]$ 和 $[i + 1, r]$ 这样的比 $[l, r]$ 更小的区间。**
123+
124+
这引导我们使用「区间 DP」进行求解。
125+
126+
**定义 $f[l][r]$ 为考虑在 $[l, r]$ 范围内进行猜数的最小成本。**
127+
128+
不失一般性的考虑 $f[l][r]$ 该如何计算。**同样的,我们可决策的部分为「选择猜哪个数 $x$」,而不可决策的是「选择某个数 $x$ 之后(假设没有猜中),真实值在落在哪边」。**
129+
130+
我们对本次选择哪个数进行讨论,假设本次选择的数值为 $x$ ( $l <= x <= r$ ),则有 $cur = \max(f[l][x - 1], f[x + 1][r]) + x$
131+
132+
最终的 $f[l][r]$ 为所有可选的数值 $x$ 中的最小值。
133+
134+
代码:
135+
```Java
136+
class Solution {
137+
public int getMoneyAmount(int n) {
138+
int[][] f = new int[n + 10][n + 10];
139+
for (int len = 2; len <= n; len++) {
140+
for (int l = 1; l + len - 1 <= n; l++) {
141+
int r = l + len - 1;
142+
f[l][r] = 0x3f3f3f3f;
143+
for (int x = l; x <= r; x++) {
144+
int cur = Math.max(f[l][x - 1], f[x + 1][r]) + x;
145+
f[l][r] = Math.min(f[l][r], cur);
146+
}
147+
}
148+
}
149+
return f[1][n];
150+
}
151+
}
152+
```
153+
* 时间复杂度:$O(n^3)$
154+
* 空间复杂度:$O(n^2)$
155+
156+
---
157+
158+
### 最后
159+
160+
这是我们「刷穿 LeetCode」系列文章的第 `No.375` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
161+
162+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
163+
164+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
165+
166+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
167+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /