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 ea12e10

Browse files
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)

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