@@ -4,7 +4,9 @@ LeetCode 上有很多小岛题,虽然官方没有这个标签, 但是在我
44
55## 套路
66
7- 这种题目的套路都是 DFS,从一个或多个入口 DFS即可。 DFS 的时候,我们往四个方向延伸即可。
7+ 这种题目的套路都是 DFS,从一个或多个入口 DFS 即可。 DFS 的时候,我们往四个方向延伸即可。
8+
9+ 一个最经典的代码模板:
810
911``` py
1012seen = set ()
@@ -32,8 +34,7 @@ for i in range(M):
3234 dfs(i, j)
3335```
3436
35-
36- 有时候我们甚至可以不用 visited 来标记每个 cell 的访问情况, 而是直接原地标记,这种算法的空间复杂度会更好。
37+ 有时候我们甚至可以不用 visited 来标记每个 cell 的访问情况, 而是直接原地标记,这种算法的空间复杂度会更好。这也是一个很常用的技巧, 大家要熟练掌握。
3738
3839``` py
3940def dfs (i , j ):
@@ -65,5 +66,73 @@ for i in range(M):
6566- [ 200. 岛屿数量] ( https://github.com/azl397985856/leetcode/blob/master/problems/200.number-of-islands.md )
6667- [ 695. 岛屿的最大面积] ( https://leetcode-cn.com/problems/max-area-of-island/solution/695-dao-yu-de-zui-da-mian-ji-dfspython3-by-fe-luci/ )
6768- [ 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+ 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
68137
69- 上面三道题都可以使用常规的 DFS 来做。 并且递归的方向都是上下左右四个方向。更有意思的是,都可以采用原地修改的方式,来减少开辟 visited 的空间。
138+ ![ ] ( https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg )
0 commit comments