Skip to content

Commit ea12e10

Browse files
committed
update content
1 parent 02891de commit ea12e10

File tree

3 files changed

+4
-235
lines changed

3 files changed

+4
-235
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ PDF 共两本,一本《labuladong 的算法秘籍》类似教材,帮你系
266266

267267
* [手把手刷图算法](https://labuladong.online/algo/)
268268
* [图论基础及遍历算法](https://labuladong.online/algo/data-structure/graph-traverse/)
269-
* [众里寻他千百度:名流问题](https://labuladong.online/algo/frequency-interview/find-celebrity/)
270269
* [环检测及拓扑排序算法](https://labuladong.online/algo/data-structure/topological-sort/)
270+
* [众里寻他千百度:名流问题](https://labuladong.online/algo/frequency-interview/find-celebrity/)
271271
* [二分图判定算法](https://labuladong.online/algo/data-structure/bipartite-graph/)
272272
* [并查集(Union-Find)算法](https://labuladong.online/algo/data-structure/union-find/)
273273
* [Kruskal 最小生成树算法](https://labuladong.online/algo/data-structure/kruskal/)

数据结构系列/dijkstra算法.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ void levelTraverse(TreeNode root) {
325325
| [286. Walls and Gates](https://leetcode.com/problems/walls-and-gates/?show=1)🔒 | [286. 墙与门](https://leetcode.cn/problems/walls-and-gates/?show=1)🔒 |
326326
| [310. Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees/?show=1) | [310. 最小高度树](https://leetcode.cn/problems/minimum-height-trees/?show=1) |
327327
| [329. Longest Increasing Path in a Matrix](https://leetcode.com/problems/longest-increasing-path-in-a-matrix/?show=1) | [329. 矩阵中的最长递增路径](https://leetcode.cn/problems/longest-increasing-path-in-a-matrix/?show=1) |
328+
| [505. The Maze II](https://leetcode.com/problems/the-maze-ii/?show=1)🔒 | [505. 迷宫 II](https://leetcode.cn/problems/the-maze-ii/?show=1)🔒 |
328329
| [542. 01 Matrix](https://leetcode.com/problems/01-matrix/?show=1) | [542. 01 矩阵](https://leetcode.cn/problems/01-matrix/?show=1) |
329330

330331
</details>

算法思维系列/花式遍历.md

Lines changed: 2 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -100,238 +100,6 @@ s = "labuladong world hello"
100100

101101
**旨在说明,有时候咱们拍脑袋的常规思维,在计算机看来可能并不是最优雅的;但是计算机觉得最优雅的思维,对咱们来说却不那么直观**。也许这就是算法的魅力所在吧。
102102

103-
回到之前说的顺时针旋转二维矩阵的问题,常规的思路就是去寻找原始坐标和旋转后坐标的映射规律,但我们是否可以让思维跳跃跳跃,尝试把矩阵进行反转、镜像对称等操作,可能会出现新的突破口。
104-
105-
**我们可以先将 `n x n` 矩阵 `matrix` 按照左上到右下的对角线进行镜像对称**
106-
107-
![](https://labuladong.online/algo/images/花式遍历/2.jpeg)
108-
109-
**然后再对矩阵的每一行进行反转**
110-
111-
![](https://labuladong.online/algo/images/花式遍历/3.jpeg)
112-
113-
**发现结果就是 `matrix` 顺时针旋转 90 度的结果**
114-
115-
![](https://labuladong.online/algo/images/花式遍历/4.jpeg)
116-
117-
将上述思路翻译成代码,即可解决本题:
118-
119-
<!-- muliti_language -->
120-
```java
121-
// 将二维矩阵原地顺时针旋转 90 度
122-
public void rotate(int[][] matrix) {
123-
int n = matrix.length;
124-
// 先沿对角线镜像对称二维矩阵
125-
for (int i = 0; i < n; i++) {
126-
for (int j = i; j < n; j++) {
127-
// swap(matrix[i][j], matrix[j][i]);
128-
int temp = matrix[i][j];
129-
matrix[i][j] = matrix[j][i];
130-
matrix[j][i] = temp;
131-
}
132-
}
133-
// 然后反转二维矩阵的每一行
134-
for (int[] row : matrix) {
135-
reverse(row);
136-
}
137-
}
138-
139-
// 反转一维数组
140-
void reverse(int[] arr) {
141-
int i = 0, j = arr.length - 1;
142-
while (j > i) {
143-
// swap(arr[i], arr[j]);
144-
int temp = arr[i];
145-
arr[i] = arr[j];
146-
arr[j] = temp;
147-
i++;
148-
j--;
149-
}
150-
}
151-
```
152-
153-
<visual slug='rotate-image'/>
154-
155-
肯定有读者会问,如果没有做过这道题,怎么可能想到这种思路呢?
156-
157-
是的,没做过这类题目,确实不好想到这种思路,但你这不是做过了么?所谓会者不难难者不会,你这辈子估计都忘不掉了。
158-
159-
**既然说道这里,我们可以发散一下,如何将矩阵逆时针旋转 90 度呢**
160-
161-
思路是类似的,只要通过另一条对角线镜像对称矩阵,然后再反转每一行,就得到了逆时针旋转矩阵的结果:
162-
163-
![](https://labuladong.online/algo/images/花式遍历/5.jpeg)
164-
165-
翻译成代码如下:
166-
167-
<!-- muliti_language -->
168-
```java
169-
// 将二维矩阵原地逆时针旋转 90 度
170-
void rotate2(int[][] matrix) {
171-
int n = matrix.length;
172-
// 沿左下到右上的对角线镜像对称二维矩阵
173-
for (int i = 0; i < n; i++) {
174-
for (int j = 0; j < n - i; j++) {
175-
// swap(matrix[i][j], matrix[n-j-1][n-i-1])
176-
int temp = matrix[i][j];
177-
matrix[i][j] = matrix[n - j - 1][n - i - 1];
178-
matrix[n - j - 1][n - i - 1] = temp;
179-
}
180-
}
181-
// 然后反转二维矩阵的每一行
182-
for (int[] row : matrix) {
183-
reverse(row);
184-
}
185-
}
186-
187-
void reverse(int[] arr) { /* 见上文 */}
188-
```
189-
190-
至此,旋转矩阵的问题就解决了。
191-
192-
### 矩阵的螺旋遍历
193-
194-
我的公众号动态规划系列文章经常需要遍历二维 `dp` 数组,但难点在于状态转移方程而不是数组的遍历,顶多就是倒序遍历。
195-
196-
但接下来我们讲一下力扣第 54 题「螺旋矩阵」,看一看二维矩阵可以如何花式遍历:
197-
198-
<Problem slug="spiral-matrix" />
199-
200-
函数签名如下:
201-
202-
<!-- muliti_language -->
203-
```java
204-
List<Integer> spiralOrder(int[][] matrix)
205-
```
206-
207-
**解题的核心思路是按照右、下、左、上的顺序遍历数组,并使用四个变量圈定未遍历元素的边界**
208-
209-
![](https://labuladong.online/algo/images/花式遍历/6.png)
210-
211-
随着螺旋遍历,相应的边界会收缩,直到螺旋遍历完整个数组:
212-
213-
![](https://labuladong.online/algo/images/花式遍历/7.png)
214-
215-
只要有了这个思路,翻译出代码就很容易了:
216-
217-
<!-- muliti_language -->
218-
```java
219-
List<Integer> spiralOrder(int[][] matrix) {
220-
int m = matrix.length, n = matrix[0].length;
221-
int upper_bound = 0, lower_bound = m - 1;
222-
int left_bound = 0, right_bound = n - 1;
223-
List<Integer> res = new LinkedList<>();
224-
// res.size() == m * n 则遍历完整个数组
225-
while (res.size() < m * n) {
226-
if (upper_bound <= lower_bound) {
227-
// 在顶部从左向右遍历
228-
for (int j = left_bound; j <= right_bound; j++) {
229-
res.add(matrix[upper_bound][j]);
230-
}
231-
// 上边界下移
232-
upper_bound++;
233-
}
234-
235-
if (left_bound <= right_bound) {
236-
// 在右侧从上向下遍历
237-
for (int i = upper_bound; i <= lower_bound; i++) {
238-
res.add(matrix[i][right_bound]);
239-
}
240-
// 右边界左移
241-
right_bound--;
242-
}
243-
244-
if (upper_bound <= lower_bound) {
245-
// 在底部从右向左遍历
246-
for (int j = right_bound; j >= left_bound; j--) {
247-
res.add(matrix[lower_bound][j]);
248-
}
249-
// 下边界上移
250-
lower_bound--;
251-
}
252-
253-
if (left_bound <= right_bound) {
254-
// 在左侧从下向上遍历
255-
for (int i = lower_bound; i >= upper_bound; i--) {
256-
res.add(matrix[i][left_bound]);
257-
}
258-
// 左边界右移
259-
left_bound++;
260-
}
261-
}
262-
return res;
263-
}
264-
```
265-
266-
力扣第 59 题「螺旋矩阵 II」也是类似的题目,只不过是反过来,让你按照螺旋的顺序生成矩阵:
267-
268-
<Problem slug="spiral-matrix-ii" />
269-
270-
函数签名如下:
271-
272-
<!-- muliti_language -->
273-
```java
274-
int[][] generateMatrix(int n)
275-
```
276-
277-
有了上面的铺垫,稍微改一下代码即可完成这道题:
278-
279-
<!-- muliti_language -->
280-
```java
281-
int[][] generateMatrix(int n) {
282-
int[][] matrix = new int[n][n];
283-
int upper_bound = 0, lower_bound = n - 1;
284-
int left_bound = 0, right_bound = n - 1;
285-
// 需要填入矩阵的数字
286-
int num = 1;
287-
288-
while (num <= n * n) {
289-
if (upper_bound <= lower_bound) {
290-
// 在顶部从左向右遍历
291-
for (int j = left_bound; j <= right_bound; j++) {
292-
matrix[upper_bound][j] = num++;
293-
}
294-
// 上边界下移
295-
upper_bound++;
296-
}
297-
298-
if (left_bound <= right_bound) {
299-
// 在右侧从上向下遍历
300-
for (int i = upper_bound; i <= lower_bound; i++) {
301-
matrix[i][right_bound] = num++;
302-
}
303-
// 右边界左移
304-
right_bound--;
305-
}
306-
307-
if (upper_bound <= lower_bound) {
308-
// 在底部从右向左遍历
309-
for (int j = right_bound; j >= left_bound; j--) {
310-
matrix[lower_bound][j] = num++;
311-
}
312-
// 下边界上移
313-
lower_bound--;
314-
}
315-
316-
if (left_bound <= right_bound) {
317-
// 在左侧从下向上遍历
318-
for (int i = lower_bound; i >= upper_bound; i--) {
319-
matrix[i][left_bound] = num++;
320-
}
321-
// 左边界右移
322-
left_bound++;
323-
}
324-
}
325-
return matrix;
326-
}
327-
```
328-
329-
至此,两道螺旋矩阵的题目也解决了。
330-
331-
以上就是遍历二维数组的一些技巧,其他数组技巧可参见之前的文章 [前缀和数组](https://labuladong.online/algo/data-structure/prefix-sum/)[差分数组](https://labuladong.online/algo/data-structure/diff-array/)[数组双指针算法集合](https://labuladong.online/algo/essential-technique/array-two-pointers-summary/),链表相关技巧可参见 [单链表六大算法技巧汇总](https://labuladong.online/algo/essential-technique/linked-list-skills-summary/)
332-
333-
334-
335103

336104

337105
<hr>
@@ -365,6 +133,6 @@ int[][] generateMatrix(int n) {
365133

366134
**_____________**
367135

368-
**《labuladong 的算法笔记》已经出版,关注公众号查看详情;后台回复「**全家桶**」可下载配套 PDF 和刷题全家桶**
136+
本文为会员内容,请扫码关注公众号或 [点这里](https://labuladong.online/algo/practice-in-action/2d-array-traversal-summary/) 查看
369137

370-
![](https://labuladong.online/algo/images/souyisou2.png)
138+
![](https://labuladong.online/algo/images/qrcode.jpg)

0 commit comments

Comments
 (0)