@@ -4,7 +4,9 @@ LeetCode 上有很多小岛题,虽然官方没有这个标签, 但是在我
4
4
5
5
## 套路
6
6
7
- 这种题目的套路都是 DFS,从一个或多个入口 DFS即可。 DFS 的时候,我们往四个方向延伸即可。
7
+ 这种题目的套路都是 DFS,从一个或多个入口 DFS 即可。 DFS 的时候,我们往四个方向延伸即可。
8
+
9
+ 一个最经典的代码模板:
8
10
9
11
``` py
10
12
seen = set ()
@@ -32,8 +34,7 @@ for i in range(M):
32
34
dfs(i, j)
33
35
```
34
36
35
-
36
- 有时候我们甚至可以不用 visited 来标记每个 cell 的访问情况, 而是直接原地标记,这种算法的空间复杂度会更好。
37
+ 有时候我们甚至可以不用 visited 来标记每个 cell 的访问情况, 而是直接原地标记,这种算法的空间复杂度会更好。这也是一个很常用的技巧, 大家要熟练掌握。
37
38
38
39
``` py
39
40
def dfs (i , j ):
@@ -65,5 +66,73 @@ for i in range(M):
65
66
- [ 200. 岛屿数量] ( https://github.com/azl397985856/leetcode/blob/master/problems/200.number-of-islands.md )
66
67
- [ 695. 岛屿的最大面积] ( https://leetcode-cn.com/problems/max-area-of-island/solution/695-dao-yu-de-zui-da-mian-ji-dfspython3-by-fe-luci/ )
67
68
- [ 1162. 地图分析] ( https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/python-tu-jie-chao-jian-dan-de-bfs1162-di-tu-fen-x/ )
69
+ - 463 . 岛屿的周长
70
+
71
+ 上面四道题都可以使用常规的 DFS 来做。 并且递归的方向都是上下左右四个方向。更有意思的是,都可以采用原地修改的方式,来减少开辟 visited 的空间。
72
+
73
+ 其中 463 题, 只是在做 DFS 的时候,需要注意相邻的各自边长可能会被重复计算, 因此需要减去。这里我的思路是:
74
+
75
+ - 遇到陆地就加 4
76
+ - 继续判断其左侧和上方是否为陆地
77
+ - 如果是的话,会出现重复计算,这个时候重复计算的是 2,因此减去 2 即可
78
+ - 如果不是,则不会重复计算, 不予理会即可
79
+
80
+ 注意,右侧和下方的就不需要算了,否则还是会重复计算。
81
+
82
+ 代码:
83
+
84
+ ``` py
85
+ class Solution :
86
+ def islandPerimeter (self , grid : List[List[int ]]) -> int :
87
+ def dfs (i , j ):
88
+ if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != 1 :
89
+ return 0
90
+ grid[i][j] = - 1
91
+ ans = 4 + dfs(i + 1 , j) + dfs(i - 1 , j) + \
92
+ dfs(i, j + 1 ) + dfs(i, j - 1 )
93
+ if i > 0 and grid[i - 1 ][j] != 0 :
94
+ ans -= 2
95
+ if j > 0 and grid[i][j - 1 ] != 0 :
96
+ ans -= 2
97
+ return ans
98
+
99
+ m, n = len (grid), len (grid[0 ])
100
+ for i in range (m):
101
+ for j in range (n):
102
+ if grid[i][j] == 1 :
103
+ return dfs(i, j)
104
+ ```
105
+
106
+ 当然, 你选择判断右侧和下方也是一样的,只需要改** 两行** 代码即可,这两种算法没有什么区别。代码:
107
+
108
+ ``` py
109
+ class Solution :
110
+ def islandPerimeter (self , grid : List[List[int ]]) -> int :
111
+ def dfs (i , j ):
112
+ if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] != 1 :
113
+ return 0
114
+ grid[i][j] = - 1
115
+ ans = 4 + dfs(i + 1 , j) + dfs(i - 1 , j) + \
116
+ dfs(i, j + 1 ) + dfs(i, j - 1 )
117
+ # 这里需要变
118
+ if i < m - 1 and grid[i + 1 ][j] != 0 :
119
+ ans -= 2
120
+ # 这里需要变
121
+ if j < n - 1 and grid[i][j + 1 ] != 0 :
122
+ ans -= 2
123
+ return ans
124
+
125
+ m, n = len (grid), len (grid[0 ])
126
+ for i in range (m):
127
+ for j in range (n):
128
+ if grid[i][j] == 1 :
129
+ return dfs(i, j)
130
+ ```
131
+
132
+ 如果你下次碰到了小岛题目, 或者可以抽象为小岛类模型的题目,可以尝试使用本节给大家介绍的模板。这种题目的规律性很强, 类似的还有石子游戏,石子游戏大多数可以使用 DP 来做,这就是一种套路。
133
+
134
+ 大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
135
+
136
+ 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
68
137
69
- 上面三道题都可以使用常规的 DFS 来做。 并且递归的方向都是上下左右四个方向。更有意思的是,都可以采用原地修改的方式,来减少开辟 visited 的空间。
138
+ ![ ] ( https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg )
0 commit comments