Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 60d22e1

Browse files
author
lucifer
committed
feat: 小岛专题
1 parent 90a795f commit 60d22e1

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
174174
- [滑动窗口(思路 + 模板)](./thinkings/slide-window.md)
175175
- [位运算](./thinkings/bit.md)
176176
- [设计题](./thinkings/design.md)
177-
- [小岛问题](./thinkings/island.md)
177+
- [小岛问题](./thinkings/island.md)🖊
178178
- [最大公约数](./thinkings/GCD.md)
179179
- [并查集](./thinkings/union-find.md) 🆕
180180
- [前缀和](./thinkings/prefix.md) 🆕

thinkings/island.md

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ LeetCode 上有很多小岛题,虽然官方没有这个标签, 但是在我
44

55
## 套路
66

7-
这种题目的套路都是 DFS,从一个或多个入口 DFS即可。 DFS 的时候,我们往四个方向延伸即可。
7+
这种题目的套路都是 DFS,从一个或多个入口 DFS 即可。 DFS 的时候,我们往四个方向延伸即可。
8+
9+
一个最经典的代码模板:
810

911
```py
1012
seen = 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
3940
def 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

Comments
 (0)