深度优先搜索和广度优先搜索
617.合并二叉树
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
思路: 每次要存两个树节点的元祖共同遍历,直接在左树上进行操作,在循环中先将左树加上右树值,再对两个节点的左右子树判定,都为非空则入队列,否则直接赋值左树的左右子树为另一非空值。
bfs:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
q = collections.deque()
if not root1 or not root2:
return root1 if root1 else root2
q.append((root1, root2))
while q:
r1, r2 = q.popleft()
r1.val += r2.val
if r1.left and r2.left:
q.append((r1.left, r2.left))
elif not r1.left:
r1.left = r2.left
if r1.right and r2.right:
q.append((r1.right, r2.right))
elif not r1.right:
r1.right = r2.right
return root1
dfs:
思路: 在左树上操作,dfs返回树节点,每次先判断是否都为空,有空直接返回,否则左树加上右树,左树左子树和右子树分别递归,最后返回左子树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
def dfs(l, r):
if not l or not r:
return l if l else r
l.val += r.val
l.left = dfs(l.left, r.left)
l.right = dfs(l.right, r.right)
return l
return dfs(root1, root2)
116. 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
进阶:
你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
思路: pre保存每层最左节点,每次循环对下一层操作,1.在同一个父节点下,直接指向右边 2.在相邻父节点下,先判断右边是否有父节点。
循环转向右边节点
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return root
pre = root
while pre.left:
tmp = pre
while tmp:
tmp.left.next = tmp.right
if tmp.next:
tmp.right.next = tmp.next.left
tmp = tmp.next
pre = pre.left
return root
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Node') -> 'Node':
def dfs(head):
if not head:
return
left, right = head.left, head.right
while left:
left.next = right
left, right = left.right, right.left
dfs(head.left)
dfs(head.right)
dfs(root)
return root
01矩阵
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
bfs:
先将所以为0点进队列和hash集,出队列,然后广度优先搜索,找到满足条件位置,赋值 + 1 进队列进hash表。
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
seen = set()
q = collections.deque()
m, n = len(mat), len(mat[0])
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
q.append((i, j))
seen.add((i, j))
dir = [0, 1, 0, -1 ,0]
while q:
ni, nj = q.popleft()
for k in range(4):
x, y = ni + dir[k], nj + dir[k + 1]
if 0 <= x < m and 0 <= y < n and (x, y) not in seen:
mat[x][y] = mat[ni][nj] + 1
q.append((x, y))
seen.add((x, y))
return mat
动态规划:
将问题视作两个动态规划问题,一个是只能向左向上走,一个是只能向右向下走,每次更新最小值,最后得到结果。一从左上角开始遍历,二从右下角开始遍历。最后会更新到所有位置。
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
for i in range(m):
for j in range(n):
if mat[i][j] == 1:
mat[i][j] = m + n
for i in range(m):
for j in range(n):
if i >= 1:
mat[i][j] = min(mat[i][j], mat[i - 1][j] + 1)
if j >= 1:
mat[i][j] = min(mat[i][j], mat[i][j - 1] + 1)
for i in range(m-1,-1,-1):
for j in range(n-1,-1,-1):
if i < m - 1:
mat[i][j] = min(mat[i][j], mat[i + 1][j] + 1)
if j < n - 1:
mat[i][j] = min(mat[i][j], mat[i][j + 1] + 1)
return mat
994.腐烂的橘子
在给定的网格中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。
思路: 广度优先搜索,超级源点,先将烂橘子入队列,计数好橘子用于判断是否腐烂完,然后bfs,分层遍历在每层遍历递增cnt
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
q = collections.deque()
cnt = fresh = 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
fresh += 1
elif grid[i][j] == 2:
q.append((i, j))
dir = [0, 1, 0, -1, 0]
# 防止没有腐烂橘子
if q:
cnt = -1
while q:
cnt += 1
for i in range(len(q)):
ni, nj = q.popleft()
for k in range(4):
x, y = ni + dir[k], nj + dir[k + 1]
if 0 <= x < m and 0 <= y < n and grid[x][y] == 1:
fresh -= 1
grid[x][y] = 2
q.append((x, y))
return -1 if fresh != 0 else cnt