深度优先搜索和广度优先搜索

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值