Skip to content

Commit f80a528

Browse files
committed
✨feat: Add 433
1 parent ea221ab commit f80a528

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

Index/图论 DFS.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
| [310. 最小高度树](https://leetcode-cn.com/problems/minimum-height-trees/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-height-trees/solution/by-ac_oier-7xio/) | 中等 | 🤩🤩🤩🤩🤩 |
44
| [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/) | 困难 | 🤩🤩🤩🤩 |
55
| [417. 太平洋大西洋水流问题](https://leetcode-cn.com/problems/pacific-atlantic-water-flow/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/pacific-atlantic-water-flow/solution/by-ac_oier-do7d/) | 中等 | 🤩🤩🤩🤩🤩 |
6+
| [433. 最小基因变化](https://leetcode-cn.com/problems/minimum-genetic-mutation/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-genetic-mutation/solution/by-ac_oier-74b4/) | 中等 | 🤩🤩🤩🤩🤩 |
67
| [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 |
78
| [797. 所有可能的路径](https://leetcode-cn.com/problems/all-paths-from-source-to-target/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/all-paths-from-source-to-target/solution/gong-shui-san-xie-yun-yong-dfs-bao-sou-s-xlz9/) | 中等 | 🤩🤩🤩🤩 |
89
| [863. 二叉树中所有距离为 K 的结点](https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-x6hak/) | 中等 | 🤩🤩🤩🤩 |

LeetCode/431-440/433. 最小基因变化(中等).md

+79-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
这是 LeetCode 上的 **[433. 最小基因变化](https://leetcode-cn.com/problems/minimum-genetic-mutation/solution/by-ac_oier-74b4/)** ,难度为 **中等**
44

5-
Tag : 「BFS」、「双向 BFS」、「A* 算法」、「启发式搜索」
5+
Tag : 「BFS」、「双向 BFS」、「图论 DFS」、「A* 算法」、「启发式搜索」
66

77

88

@@ -49,7 +49,7 @@ Tag : 「BFS」、「双向 BFS」、「A* 算法」、「启发式搜索」
4949

5050
为了方便,我们令 $S = start$、 $T = end$,将每个基因序列视为「状态」。
5151

52-
容易想到使用 `BFS` 进行求解,并使用「哈希表」记录到达某个状态所消耗的步数(同时为了快速判断某个状态是否合法,我们使用 `Set` 结构对 $back[i]$ 进行转存)。
52+
容易想到使用 `BFS` 进行求解,并使用「哈希表」记录到达某个状态所消耗的步数(同时为了快速判断某个状态是否合法,我们使用 `Set` 结构对 $bank[i]$ 进行转存)。
5353

5454
起始将 `S` 加入队列,并更新到达 `S` 所使用的步数为 $0$,然后进行常规的 `BFS` 过程:每次取出队头元素,尝试替换当前状态的某一位,来得到新的状态(限定新状态必须合法,即必须出现在 `Set` 中),如果新状态合法并且没有在记录步数的哈希表中出现过,则将新状态入队并更新得到新状态所用步数,否则丢弃新状态。
5555

@@ -91,7 +91,7 @@ class Solution {
9191
}
9292
}
9393
```
94-
* 时间复杂度:令 $n$ 为 `bank` 的数组长度(合法状态数),将 `back` 存入 `Set` 结构复杂度为 $O(n)$,每个状态经过一步操作最多拓展出 $C = 32$ 个新基因(共有 $8$ 个位置,每个位置有 $4$ 个选择),`BFS` 过程复杂度为 $O(C * n)$。整体复杂度为 $O(C * n)$
94+
* 时间复杂度:令 $n$ 为 `bank` 的数组长度(合法状态数),将 `bank` 存入 `Set` 结构复杂度为 $O(n)$,每个状态经过一步操作最多拓展出 $C = 32$ 个新基因(共有 $8$ 个位置,每个位置有 $4$ 个选择),`BFS` 过程复杂度为 $O(C * n)$。整体复杂度为 $O(C * n)$
9595
* 空间复杂度:$O(n)$
9696

9797
---
@@ -155,7 +155,7 @@ class Solution {
155155
}
156156
}
157157
```
158-
* 时间复杂度:令 $n$ 为 `bank` 的数组长度(合法状态数),将 `back` 存入 `Set` 结构复杂度为 $O(n)$,每个状态经过一步操作最多拓展出 $C = 32$ 个新基因(共有 $8$ 个位置,每个位置有 $4$ 个选择),`BFS` 过程复杂度为 $O(C * n)$。整体复杂度为 $O(C * n)$
158+
* 时间复杂度:令 $n$ 为 `bank` 的数组长度(合法状态数),将 `bank` 存入 `Set` 结构复杂度为 $O(n)$,每个状态经过一步操作最多拓展出 $C = 32$ 个新基因(共有 $8$ 个位置,每个位置有 $4$ 个选择),`BFS` 过程复杂度为 $O(C * n)$。整体复杂度为 $O(C * n)$
159159
* 空间复杂度:$O(n)$
160160

161161
---
@@ -168,7 +168,7 @@ class Solution {
168168

169169
具体的,我们使用优先队列(堆)维护所有的状态,每次优先「启发值 = 理论最小转换步数」的状态进行优先出队拓展。
170170

171-
对「A* 算法」不了解的同学可以看前置 🧀:[发挥 A* 算法最大价值的关键点](https%3A//mp.weixin.qq.com/s?__biz%3DMzU4NDE3MTEyMA%3D%3D%26mid%3D2247489588%26idx%3D1%26sn%3D479e4c0627247ab7e20af7909f2a8b64)
171+
对「A* 算法」不了解的同学可以看前置 🧀:[发挥 A* 算法最大价值的关键点](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247489588&idx=1&sn=479e4c0627247ab7e20af7909f2a8b64)
172172

173173
代码:
174174
```Java
@@ -221,6 +221,80 @@ class Solution {
221221

222222
---
223223

224+
### 建图 + DFS
225+
226+
**`S` 和 $bank[i]$ 组成合法点集,且点集中任意两点之间存在无向边的充要条件是:点 $u$ 和点 $v$ 所代表的字符中,仅有一个位置字符不同。**
227+
228+
因此我们可以将所有的点存入 `list` 中,假设 `list` 长度为 $n$。同时为了方便,我们人为确保 `S` 出现在头部(点编号为 $1$),`T` 出现在尾部(点编号为 $n$)。
229+
230+
遍历 `list` 进行建图(对于两字符串中仅有一位置不同的点进行连边操作),然后跑一遍从 $1$ 到 $n$ 的 `DFS`
231+
232+
由于图中可能有环或无解,因此必须「设定一个最大搜索深度」并增加「最优解剪枝」,确保搜索过程结束。
233+
234+
最大搜索深度的设定可以利用反证法:如果 `S` 能够到达 `T`,那么最优路径中必然不存在环(否则可以把环去掉,得到一条更短的路径),即最优路径所经过的点的数量必然不超过 $n$。
235+
236+
代码:
237+
```Java
238+
class Solution {
239+
int N = 15, M = 15 * 15 * 2 + 50, idx = 0, loc = 1;
240+
int[] he = new int[N], e = new int[M], ne = new int[M];
241+
int n, ans;
242+
void add(int a, int b) {
243+
e[idx] = b;
244+
ne[idx] = he[a];
245+
he[a] = idx++;
246+
}
247+
void dfs(int u, int fa, int depth) {
248+
if (depth >= ans) return ; // 最优解剪枝
249+
if (u == n) {
250+
ans = depth;
251+
return ;
252+
}
253+
for (int i = he[u]; i != -1; i = ne[i]) {
254+
int j = e[i];
255+
if (j == fa) continue;
256+
dfs(j, u, depth + 1);
257+
}
258+
}
259+
public int minMutation(String S, String T, String[] bank) {
260+
List<String> list = new ArrayList<>();
261+
list.add(S);
262+
boolean ok = false;
263+
for (String s : bank) {
264+
if (s.equals(S)) continue;
265+
if (s.equals(T)) {
266+
ok = true;
267+
continue;
268+
}
269+
list.add(s);
270+
}
271+
if (!ok) return -1;
272+
list.add(T);
273+
n = list.size();
274+
ans = n;
275+
Arrays.fill(he, -1);
276+
for (int i = 0; i < n; i++) {
277+
for (int j = 0; j < n; j++) {
278+
if (i == j) continue;
279+
int cnt = 0;
280+
for (int k = 0; k < 8 && cnt <= 1; k++) {
281+
if (list.get(i).charAt(k) != list.get(j).charAt(k)) cnt++;
282+
}
283+
if (cnt == 1) {
284+
add(i + 1, j + 1); add(j + 1, i + 1);
285+
}
286+
}
287+
}
288+
dfs(1, -1, 0);
289+
return ans == n ? -1 : ans;
290+
}
291+
}
292+
```
293+
* 时间复杂度:令 `bank` 的长度为 $n$(即点集的数量级为 $n$),预处理出 `list` 的复杂度为 $O(n)$;建图操作的复杂度为 $O(C * n^2)$,其中 $C = 8$ 基因序列长度;`DFS` 过程由于设定了最大搜索深度,复杂度为 $O(n^2)$。整体复杂度为 $O(C * n^2)$
294+
* 空间复杂度:最坏情况下为完全图,复杂度为 $O(n^2)$
295+
296+
---
297+
224298
### 最后
225299

226300
这是我们「刷穿 LeetCode」系列文章的第 `No.433` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

0 commit comments

Comments
 (0)