1020. 飞地的数量
给你一个大小为 m x n
的二进制矩阵 grid
,其中 0
表示一个海洋单元格、1
表示一个陆地单元格。
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid
的边界。
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。
示例 1:
输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] 输出:3 解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。
示例 2:
输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] 输出:0 解释:所有 1 都在边界上或可以到达边界。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 500
grid[i][j]
的值为 0
或 1
from collections import deque
from typing import List
# dfs
class Solution:
def numEnclaves(self, grid: List[List[int]]) -> int:
row, colomn = len(grid), len(grid[0])
visit = [[False]*colomn for _ in range(row)]
def dfs(i, j):
if i >= 0 and i <= row-1 and j >=0 and j<=colomn-1 and grid[i][j] and not visit[i][j]:
visit[i][j] = True
for x, y in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):
dfs(x, y)
else:
return
for i in range(row):
dfs(i, 0)
dfs(i, colomn-1)
for j in range(1, colomn-1):
dfs(0, j)
dfs(row-1, j)
return sum(grid[i][j] if not visit[i][j] else 0 for i in range(row) for j in range(colomn))
# 官方题解是这样写的,注意sum可以对布尔类型做运算
# return sum(grid[i][j] and not vis[i][j] for i in range(1, m - 1) for j in range(1, n - 1))
# 官方dfs
class Solution:
def numEnclaves(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
vis = [[False] * n for _ in range(m)]
def dfs(r: int, c: int) -> None:
if r < 0 or r >= m or c < 0 or c >= n or grid[r][c] == 0 or vis[r][c]:
return
vis[r][c] = True
for x, y in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
dfs(x, y)
for i in range(m):
dfs(i, 0)
dfs(i, n - 1)
for j in range(1, n - 1):
dfs(0, j)
dfs(m - 1, j)
return sum(grid[i][j] and not vis[i][j] for i in range(1, m - 1) for j in range(1, n - 1))
# tip: sum函数可以对bool类型进行运算
a = (2==1 and not 3==1 for _ in range(10))
print([x for x in a])
print (sum([False, False]))
# bfs
class Solution:
def numEnclaves(self, grid: List[List[int]]) -> int:
row, colomn = len(grid), len(grid[0])
visit = [[False]*colomn for _ in range(row)] # dfs和bfs的关键
d = deque()
for i in range(row):
for j in range(colomn):
if i == 0 or j == 0 or i == row-1 or j == colomn-1:
if grid[i][j] == 1 and not visit[i][j]:
visit[i][j] = True
d.append((i, j))
while d: # 注意这个while循环不能写在这个if下面(结果不一样),也不知道为什么,下次注意吧,要先把要遍历的东西全放到队列里面去
i, j = d.popleft()
for x, y in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):
if x >= 0 and x <= row - 1 and y >= 0 and y <= colomn - 1 and not visit[x][y] and grid[x][y]:
d.append((x, y))
visit[x][y] = True
return sum(grid[i][j] and not visit[i][j] for i in range(1, row-1) for j in range(1, colomn-1))
注意:dfs对应着二叉树的三种递归遍历,bfs对应层序遍历
113. 路径总和 II
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5 输出:[]
示例 3:
输入:root = [1,2], targetSum = 0 输出:[]
提示:
[0, 5000]
内-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# dfs
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
def dfs(root:Optional[TreeNode], target, path:List[int], mysum:int):
if root:
path.append(root.val)
mysum += root.val
if not root.right and not root.left and mysum == target:
ret.append(path[:])
"""
这个一定要用切片,不然会发生错误(直接输出空的列表),我推测大概是因为在函数调用时,
直接append(path)是对原来的path的地址空间进行append 所以才会显示空的集合,而
path[:]相当于深拷贝了一个新的path,对这个新的path的操作就是在一个新的地址空间的
操作,不会被原地址空间的path影响
详看:https://leetcode-cn.com/problems/path-sum-ii/solution/lc113-fengwei2002-guan-yu-bu-li-jie-slic-hank/
例如a = [1,2,3]
b = a
c = a[:]
b.append(4)
c.append(5)
print(a) # [1, 2, 3, 4]
"""
dfs(root.left, target, path, mysum)
dfs(root.right, target, path, mysum) # 这两个递归函数内部是不会改变外面的mysum变量的值的
path.pop()
# mysum -= root.val 不需要这一步,因为mysum这个变量对于递归的dfs内层函数来说相当于全局变量
ret = []
path = []
dfs(root, targetSum, path, 0)
return ret