diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md
index 79ff2884..d37eba0a 100644
--- a/notes/Leetcode 题解.md
+++ b/notes/Leetcode 题解.md
@@ -985,7 +985,7 @@ public String frequencySort(String s) {
-**对颜色进行排序**
+**按颜色进行排序**
[75. Sort Colors (Medium)](https://leetcode.com/problems/sort-colors/description/)
@@ -994,6 +994,8 @@ Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
```
+题目描述:只有 0/1/2 三种颜色。
+
```java
public void sortColors(int[] nums) {
int zero = -1, one = 0, two = nums.length;
@@ -1040,7 +1042,7 @@ private void swap(int[] nums, int i, int j) {
- 4 -> {}
- 3 -> {}
-可以看到,每一轮遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di<=dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。
+可以看到,每一轮遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di<=dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。
在程序实现 BFS 时需要考虑以下问题:
@@ -1060,35 +1062,174 @@ private void swap(int[] nums, int i, int j) {
```java
public int minPathLength(int[][] grids, int tr, int tc) {
- int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
- int m = grids.length, n = grids[0].length;
- Queue queue = new LinkedList<>();
- queue.add(new Position(0, 0));
+ final int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
+ final int m = grids.length, n = grids[0].length;
+ Queue> queue = new LinkedList<>();
+ queue.add(new Pair(0, 0));
int pathLength = 0;
while (!queue.isEmpty()) {
int size = queue.size();
pathLength++;
while (size-- > 0) {
- Position cur = queue.poll();
+ Pair cur = queue.poll();
for (int[] d : direction) {
- Position next = new Position(cur.r + d[0], cur.c + d[1]);
- if (next.r < 0 || next.r >= m || next.c < 0 || next.c >= n) continue;
- grids[next.r][next.c] = 0;
- if (next.r == tr && next.c == tc) return pathLength;
+ Pair next = new Pair(cur.getKey() + d[0], cur.getValue() + d[1]);
+ if (next.getKey() < 0 || next.getValue() >= m || next.getKey() < 0 || next.getValue() >= n)
+ continue;
+ grids[next.getKey()][next.getValue()] = 0; // 标记
+ if (next.getKey() == tr && next.getValue() == tc)
+ return pathLength;
queue.add(next);
}
}
}
return -1;
}
+```
-private class Position {
- int r, c;
+**组成整数的最小平方数数量**
- Position(int r, int c) {
- this.r = r;
- this.c = c;
+[279. Perfect Squares (Medium)](https://leetcode.com/problems/perfect-squares/description/)
+
+```html
+For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
+```
+
+可以将每个整数看成图中的一个节点,如果两个整数只差为一个平方数,那么这两个整数所在的节点就有一条边。
+
+要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。
+
+本题也可以用动态规划求解,在之后动态规划部分中会再次出现。
+
+```java
+public int numSquares(int n) {
+ List squares = generateSquares(n);
+ Queue queue = new LinkedList<>();
+ boolean[] marked = new boolean[n + 1];
+ queue.add(n);
+ marked[n] = true;
+ int num = 0;
+ while (!queue.isEmpty()) {
+ int size = queue.size();
+ num++;
+ while (size-- > 0) {
+ int cur = queue.poll();
+ for (int s : squares) {
+ int next = cur - s;
+ if (next < 0)
+ break;
+ if (next == 0)
+ return num;
+ if (marked[next])
+ continue;
+ marked[next] = true;
+ queue.add(cur - s);
+ }
+ }
}
+ return n;
+}
+
+private List generateSquares(int n) {
+ List squares = new ArrayList<>();
+ int square = 1;
+ int diff = 3;
+ while (square <= n) {
+ squares.add(square);
+ square += diff;
+ diff += 2;
+ }
+ return squares;
+}
+```
+
+**最短单词路径**
+
+[127. Word Ladder (Medium)](https://leetcode.com/problems/word-ladder/description/)
+
+```html
+Input:
+beginWord = "hit",
+endWord = "cog",
+wordList = ["hot","dot","dog","lot","log","cog"]
+
+Output: 5
+
+Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
+return its length 5.
+```
+
+```html
+Input:
+beginWord = "hit"
+endWord = "cog"
+wordList = ["hot","dot","dog","lot","log"]
+
+Output: 0
+
+Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
+```
+
+题目描述:要找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。
+
+```java
+public int ladderLength(String beginWord, String endWord, List wordList) {
+ wordList.add(beginWord);
+ int N = wordList.size();
+ int start = N - 1;
+ int end = 0;
+ while (end < N && !wordList.get(end).equals(endWord))
+ end++;
+ if (end == N)
+ return 0;
+ List[] graphic = buildGraphic(wordList);
+ return getShortestPath(graphic, start, end);
+}
+
+private List[] buildGraphic(List wordList) {
+ int N = wordList.size();
+ List[] graphic = new List[N];
+ for (int i = 0; i < N; i++) {
+ graphic[i] = new ArrayList<>();
+ for (int j = 0; j < N; j++) {
+ if (isConnect(wordList.get(i), wordList.get(j)))
+ graphic[i].add(j);
+ }
+ }
+ return graphic;
+}
+
+private boolean isConnect(String s1, String s2) {
+ int diffCnt = 0;
+ for (int i = 0; i < s1.length() && diffCnt <= 1; i++) {
+ if (s1.charAt(i) != s2.charAt(i))
+ diffCnt++;
+ }
+ return diffCnt == 1;
+}
+
+private int getShortestPath(List[] graphic, int start, int end) {
+ Queue queue = new LinkedList<>();
+ boolean[] marked = new boolean[graphic.length];
+ queue.add(start);
+ marked[start] = true;
+ int path = 1;
+ while (!queue.isEmpty()) {
+ int size = queue.size();
+ path++;
+ while (size-- > 0) {
+ int cur = queue.poll();
+ for (int next : graphic[cur]) {
+ if (next == end)
+ return path;
+ if (marked[next])
+ continue;
+ marked[next] = true;
+ queue.add(next);
+ }
+ }
+ }
+ return 0;
}
```