1.0200. 岛屿数量
1.1 题目大意
描述:给定一个由字符 '1'
(陆地)和字符 '0'
(水)组成的的二维网格 grid
。
要求:计算网格中岛屿的数量。
说明:
- 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
- 此外,你可以假设该网格的四条边均被水包围。
- 𝑚==𝑔𝑟𝑖𝑑.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑛==𝑔𝑟𝑖𝑑[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ。
- 1≤𝑚,𝑛≤300。
grid[i][j]
的值为'0'
或'1'
。
示例:
输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
class Solution:
def numIslands(self, grid):
def dfs(grid,i,j):
#在不出界的情况下,如果值为1
if i>=0 and i<m and j>=0 and j<n and grid[i][j] == "1":
grid[i][j] = "0" #将访问过的置为0
#依次遍历上下左右
dfs(grid,i+1,j)
dfs(grid,i-1,j)
dfs(grid,i,j-1)
dfs(grid,i,j+1)
#不是矩阵返回0
if not grid:
return 0
m = len(grid) #行
n = len(grid[0]) #列
count = 0 #计数
for i in range(m): #遍历行
for j in range(n) : #遍历列
if grid[i][j] =="1": #网格值为1
dfs(grid,i,j) #dfs遍历
count += 1
return count
2.0133. 克隆图
2.1 题目大意
描述:以每个节点的邻接列表形式(二维列表)给定一个无向连通图,其中 adjList[i]
表示值为 i + 1
的节点的邻接列表,adjList[i][j]
表示值为 i + 1
的节点与值为 adjList[i][j]
的节点有一条边。
要求:返回该图的深拷贝。
说明:
- 节点数不超过
100
。 - 每个节点值 𝑁𝑜𝑑𝑒.𝑣𝑎𝑙 都是唯一的,1≤𝑁𝑜𝑑𝑒.𝑣𝑎𝑙≤100。
- 无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
- 由于图是无向的,如果节点
p
是节点q
的邻居,那么节点q
也必须是节点p
的邻居。 - 图是连通图,你可以从给定节点访问到所有节点。
示例:
输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
输入:adjList = [[2],[1]]
输出:[[2],[1]]
class Solution:
def cloneGraph(self, node):
if not node:
return None
# 构造所有新节点以及新旧节点对应表
hashmap = {}
queue = collections.deque([node])
visited = {node}
while queue:
old = queue.popleft()
new = Node(val=old.val)
hashmap[old] = new
for neighbor in old.neighbors:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
# 构造所有新节点之间的关系
for old, new in hashmap.items():
for neighbor in old.neighbors:
new.neighbors.append(hashmap[neighbor])
return hashmap[node]
3.0494. 目标和
3.1 题目大意
描述:给定一个整数数组 nums
和一个整数 target
。数组长度不超过 20
。向数组中每个整数前加 +
或 -
。然后串联起来构造成一个表达式。
要求:返回通过上述方法构造的、运算结果等于 target
的不同表达式数目。
说明:
- 1≤𝑛𝑢𝑚𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤20。
- 0≤𝑛𝑢𝑚𝑠[𝑖]≤1000。
- 0≤𝑠𝑢𝑚(𝑛𝑢𝑚𝑠[𝑖])≤1000。
- −1000≤𝑡𝑎𝑟𝑔𝑒𝑡≤1000。
示例:
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
输入:nums = [1], target = 1
输出:1
class Solution:
def findTargetSumWays(self, nums, target):
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2
def dfs(i, c):
if i < 0:
return 1 if c == 0 else 0
if c < nums[i]:
return dfs(i - 1, c)
return dfs(i - 1, c) + dfs(i - 1, c - nums[i])
return dfs(len(nums) - 1, target)
1.0841. 钥匙和房间
1.1 题目大意
描述:有 n
个房间,编号为 0
~ n - 1
,每个房间都有若干把钥匙,每把钥匙上都有一个编号,可以开启对应房间号的门。最初,除了 0
号房间外其他房间的门都是锁着的。
现在给定一个二维数组 rooms
,rooms[i][j]
表示第 i
个房间的第 j
把钥匙所能开启的房间号。
要求:判断是否能开启所有房间的门。如果能开启,则返回 True
。否则返回 False
。
说明:
- 𝑛==𝑟𝑜𝑜𝑚𝑠.𝑙𝑒𝑛𝑔𝑡ℎ。
- 2≤𝑛≤1000。
- 0≤𝑟𝑜𝑜𝑚𝑠[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ≤1000。
- 1≤𝑠𝑢𝑚(𝑟𝑜𝑜𝑚𝑠[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ)≤3000。
- 0≤𝑟𝑜𝑜𝑚𝑠[𝑖][𝑗]<𝑛。
- 所有 𝑟𝑜𝑜𝑚𝑠[𝑖] 的值互不相同。
示例:
输入:rooms = [[1],[2],[3],[]]
输出:True
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。
输入:rooms = [[1,3],[3,0,1],[2],[0]]
输出:False
解释:我们不能进入 2 号房间。
class Solution:
def canVisitAllRooms(self, rooms):
def dfs(room):
vis.add(room) #给集合添加元素
for key in rooms[room]:
if key not in vis:
dfs(key)
vis = set()
dfs(0)
return len(vis) == len(rooms)
2.0695. 岛屿的最大面积
2.1 题目大意
描述:给定一个只包含 0
、1
元素的二维数组,1
代表岛屿,0
代表水。一座岛的面积就是上下左右相邻的 1
所组成的连通块的数目。
要求:计算出最大的岛屿面积。
说明:
- 𝑚==𝑔𝑟𝑖𝑑.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑛==𝑔𝑟𝑖𝑑[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ。
- 1≤𝑚,𝑛≤50。
- 𝑔𝑟𝑖𝑑[𝑖][𝑗] 为 `0` 或 `1`。
示例:
输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。
输入:grid = [[0,0,0,0,0,0,0,0]]
输出:0
class Solution(object):
def maxAreaOfIsland(self, grid):
def dfs(i,j):
if i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]==0:
return 0
count = 1
grid[i][j] = 0
count = count+dfs(i-1,j)
count = count + dfs(i+1,j)
count = count + dfs(i,j-1)
count = count + dfs(i, j+1)
return count
maxarea = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
maxarea = max(maxarea,dfs(i,j))
return maxarea
3.0130. 被围绕的区域
3.1 题目大意
描述:给定一个 m * n
的矩阵 board
,由若干字符 X
和 O
构成。
要求:找到所有被 X
围绕的区域,并将这些区域里所有的 O
用 X
填充。
说明:
- 𝑚==𝑏𝑜𝑎𝑟𝑑.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑛==𝑏𝑜𝑎𝑟𝑑[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ。
- 1<=𝑚,𝑛<=200。
- 𝑏𝑜𝑎𝑟𝑑[𝑖][𝑗] 为 `'X'` 或 `'O'`。
示例:
输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
输入:board = [["X"]]
输出:[["X"]]
class Solution(object):
def solve(self, board):
m = len(board)
n = len(board[0])
directions = [(0,-1),(0,1),(-1,0),(1,0)]
def dfs(x,y):
if 0<=x<m and 0<=y<n and board[x][y]=='O':
board[x][y]='M'
for dx,dy in directions:
newx = x+dx
newy = y+dy
dfs(newx,newy)
for i in range(m):
dfs(i,0)
dfs(i,n-1)
for j in range(n):
dfs(0,j)
dfs(m-1,j)
for i in range(m):
for j in range(n):
if board[i][j]=='O':
board[i][j]='X'
if board[i][j]=='M':
board[i][j]='O'
return board
1.0417. 太平洋大西洋水流问题
1.1 题目大意
描述:给定一个 m * n
大小的二维非负整数矩阵 heights
来表示一片大陆上各个单元格的高度。heights[i][j]
表示第 i
行第 j
列所代表的陆地高度。这个二维矩阵所代表的陆地被太平洋和大西洋所包围着。左上角是「太平洋」,右下角是「大西洋」。规定水流只能按照上、下、左、右四个方向流动,且只能从高处流到低处,或者在同等高度上流动。
要求:找出代表陆地的二维矩阵中,水流既可以从该处流动到太平洋,又可以流动到大西洋的所有坐标。以二维数组 res
的形式返回,其中 res[i] = [ri, ci]
表示雨水从单元格 (ri, ci)
既可流向太平洋也可流向大西洋。
说明:
- 𝑚==ℎ𝑒𝑖𝑔ℎ𝑡𝑠.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑛==ℎ𝑒𝑖𝑔ℎ𝑡𝑠[𝑟].𝑙𝑒𝑛𝑔𝑡ℎ。
- 1≤𝑚,𝑛≤200。
- 0≤ℎ𝑒𝑖𝑔ℎ𝑡𝑠[𝑟][𝑐]≤105。
示例:
输入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
输出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
输入: heights = [[2,1],[1,2]]
输出: [[0,0],[0,1],[1,0],[1,1]]
class Solution:
def pacificAtlantic(self, matrix):
if not matrix or not matrix[0]:
return []
m, n = len(matrix), len(matrix[0])
def _is_valid(x, y):
return 0 <= x < m and 0 <= y < n
def _get_near(x, y):
return [(xx, yy) for (xx, yy) in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)] if _is_valid(xx, yy)]
queue1 = collections.deque([])
visited1 = set()
queue2 = collections.deque([])
visited2 = set()
# 标记地图边缘位置
for i in range(m):
queue1.append((i, 0))
visited1.add((i, 0))
queue2.append((i, n - 1))
visited2.add((i, n - 1))
for j in range(n):
queue1.append((0, j))
visited1.add((0, j))
queue2.append((m - 1, j))
visited2.add((m - 1, j))
# 标记太平洋
while queue1:
i1, j1 = queue1.popleft()
for i2, j2 in _get_near(i1, j1):
if matrix[i2][j2] >= matrix[i1][j1] and (i2, j2) not in visited1:
visited1.add((i2, j2))
queue1.append((i2, j2))
# 标记大西洋
while queue2:
i1, j1 = queue2.popleft()
for i2, j2 in _get_near(i1, j1):
if matrix[i2][j2] >= matrix[i1][j1] and (i2, j2) not in visited2:
visited2.add((i2, j2))
queue2.append((i2, j2))
# 生成结果
return [[i, j] for (i, j) in (visited1 & visited2)]
2.1020. 飞地的数量
2.1 题目大意
描述:给定一个二维数组 grid
,每个单元格为 0
(代表海)或 1
(代表陆地)。我们可以从一个陆地走到另一个陆地上(朝四个方向之一),然后从边界上的陆地离开网络的边界。
要求:返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
说明:
- 𝑚==𝑔𝑟𝑖𝑑.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑛==𝑔𝑟𝑖𝑑[𝑖].𝑙𝑒𝑛𝑔𝑡ℎ。
- 1≤𝑚,𝑛≤500。
- 𝑔𝑟𝑖𝑑[𝑖][𝑗] 的值为 0 或 1。
示例:
输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。
Copy to clipboardErrorCopied
输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。
class Solution:
def numEnclaves(self, A):
m, n = len(A), len(A[0])
def _is_valid(x, y):
return 0 <= x < m and 0 <= y < n
def _get_neighbors(x1, y1):
return [(x2, y2) for (x2, y2) in [(x1 - 1, y1), (x1 + 1, y1), (x1, y1 - 1), (x1, y1 + 1)]
if _is_valid(x2, y2)]
# 遍历半岛
mainland = set()
queue = collections.deque()
for i in range(m):
if A[i][0] == 1:
queue.append((i, 0))
mainland.add((i, 0))
if A[i][n - 1] == 1:
queue.append((i, n - 1))
mainland.add((i, n - 1))
for j in range(1, n - 1):
if A[0][j] == 1:
queue.append((0, j))
mainland.add((0, j))
if A[m - 1][j] == 1:
queue.append((m - 1, j))
mainland.add((m - 1, j))
while queue:
i1, j1 = queue.popleft()
for i2, j2 in _get_neighbors(i1, j1):
if A[i2][j2] == 1 and (i2, j2) not in mainland:
queue.append((i2, j2))
mainland.add((i2, j2))
# 遍历岛屿
island = set()
for i in range(m):
for j in range(n):
if A[i][j] == 1 and (i, j) not in mainland and (i, j) not in island:
island.add((i, j))
queue = collections.deque([(i, j)])
while queue:
i1, j1 = queue.popleft()
for i2, j2 in _get_neighbors(i1, j1):
if A[i2][j2] == 1 and (i2, j2) not in mainland and (i2, j2) not in island:
queue.append((i2, j2))
island.add((i2, j2))
return len(island)
3.1254. 统计封闭岛屿的数目
3.1 题目大意
描述:给定一个二维矩阵 grid
,每个位置要么是陆地(记号为 0
)要么是水域(记号为 1
)。
我们从一块陆地出发,每次可以往上下左右 4
个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿完全由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为「封闭岛屿」。
要求:返回封闭岛屿的数目。
说明:
- 1≤𝑔𝑟𝑖𝑑.𝑙𝑒𝑛𝑔𝑡ℎ,𝑔𝑟𝑖𝑑[0].𝑙𝑒𝑛𝑔𝑡ℎ≤100。
- 0≤𝑔𝑟𝑖𝑑[𝑖][𝑗]≤1。
示例:
输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。
Copy to clipboardErrorCopied
输入:grid = [[0,0,1,0,0],[0,1,0,1,0],[0,1,1,1,0]]
输出:1
class Solution(object):
def closedIsland(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m, n = len(grid), len(grid[0])
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
def dfs(x0, y0):
if grid[x0][y0] == 0:
grid[x0][y0] = -1
for k in range(4):
x = x0 + dx[k]
y = y0 + dy[k]
if 0 < x < m and 0 < y < n and grid[x][y] == 0:
dfs(x, y)
for j in range(n):
dfs(0, j)
for j in range(n):
dfs(m - 1, j)
for i in range(m):
dfs(i, 0)
for i in range(m):
dfs(i, n - 1)
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 0:
res += 1
dfs(i, j)
return res