DFS(一)

94. 二叉树的中序遍历

# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # # 递归 中序遍历 左根右
        # res = []
        # if not root:
        #     return res

        # def dfs(node):
        #     if node.left:
        #         dfs(node.left)
        #     res.append(node.val)
        #     if node.right:
        #         dfs(node.right)
        #     return
            
        # dfs(root)
        # return res

        # 迭代 中序遍历 左根右
        res = []
        stack = []
        while root or len(stack) > 0:
            # 遍历左节点,放入栈
            while root:
                stack.append(root)
                root = root.left
            # 中间处理
            root = stack.pop()
            # print(root.val)
            res.append(root.val)
            # 遍历右节点
            root = root.right
        return res

98. 验证二叉搜索树

# 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 __init__(self):
        self.preNode = float("-inf")
    
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        # # 返回是否是二叉搜索树
        # # 递归时传入当前树的最小值和最大值
        # # 左子树小于根节点,递归左子树,最小值需要继承,最大值就是根节点值
        # # 右子树大于根节点,递归右子树,最大值需要继承,最小值就是根节点值
        # def isValid(node, min_val, max_val):
        #     if not node:
        #         return True
        #     return node.val < max_val and node.val > min_val and isValid(node.left, min_val, node.val) and isValid(node.right, node.val, max_val)

        # return isValid(root.left, float('-inf'), root.val) and isValid(root.right, root.val, float('inf'))

        # # 中序遍历 二叉搜索树中序遍历是递增的
        # # 返回 node 树是否满足中序遍历递增
        # def dfs(node):
        #     if not node:
        #         return True
        #     res = dfs(node.left)

        #     # 中间位置加入判断逻辑
        #     # print(node.val)
        #     if node.val > self.preNode:
        #         self.preNode = node.val
        #     else:
        #         return False
            
        #     res = res and dfs(node.right)
        #     return res
        
        # return dfs(root)

        # 迭代 中序遍历 左根右
        res = []
        stack = []
        preNode = float('-inf')
        while root or len(stack) > 0:
            # 遍历左节点,放入栈
            while root:
                stack.append(root)
                root = root.left
            # 中间处理
            root = stack.pop()
            if root.val > preNode:
                preNode = root.val
            else:
                return False
            # 遍历右节点
            root = root.right
        return True

99. 恢复二叉搜索树

# 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 recoverTree(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        # 中序遍历,找到不符合递增关系的两个位置,重新遍历修改节点值
        res = []  # 中序遍历结果
        def dfs(node):
            if not node:
                return
            dfs(node.left)
            res.append(node.val)
            dfs(node.right)
        dfs(root)

        # 找到不符合递增关系的位置 值
        x, y = float('inf'), float('inf')
        for i in range(1, len(res)):
            if res[i] < res[i-1]:
                y = res[i]
                if x == float('inf'):
                    x = res[i-1]
                else:
                    break
        print(x, y)
        
        # 重新遍历修改节点值
        def dfs_re(node, x, y):
            if not node:
                return
            dfs_re(node.left, x, y)
            if node.val == x:
                node.val = y
            elif node.val == y:
                node.val = x
            dfs_re(node.right, x, y)
        dfs_re(root, x, y)
        return 

        # 维护 pre 节点,遍历过程中直接找到异常节点

        # Morris 中序遍历

100. 相同的树

# 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 isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and not q:
            return True
        if not p or not q:
            return False
        return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

101. 对称二叉树

# 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 isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        
        def helper(left, right):
            if not left and not right:
                return True
            if not left or not right:
                return False
            return left.val == right.val and helper(left.left, right.right) and helper(left.right, right.left)

        return helper(root.left, root.right)

104. 二叉树的最大深度

# 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 maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

112. 路径总和

# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        
        def helper(node, targetSum):
            if not node.left and not node.right and node.val == targetSum:
                return True
            is_left, is_right = False, False
            if node.left:
                is_left = helper(node.left, targetSum - node.val)
            if node.right:
                is_right = helper(node.right, targetSum - node.val)
            return is_left or is_right
        
        return helper(root, targetSum)
    
    # if not root:
    #     return False
    # if not root.left and not root.right:
    #     return sum == root.val
    # return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)

    # 广度优先搜索

113. 路径总和 II

# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        # 回溯
        res = []
        ans = []
        if not root:
            return res

        def dfs(node, target):
            # 边界条件,达到叶子节点,满足条件的 ans 写入 res
            if not node.left and not node.right and node.val == target:
                ans.append(node.val)
                res.append(ans[:])  # 注意 ans[:], 不能是 res.append(ans)
                return
            ans.append(node.val)
            # 做选择,结果写入 ans
            if node.left:
                dfs(node.left, target - node.val)
                # 退出选择,回到根节点
                ans.pop()
            if node.right:
                dfs(node.right, target - node.val)
                # 退出选择,回到根节点
                ans.pop() 

        dfs(root, targetSum)
        return res

114. 二叉树展开为链表

# 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 __init__(self):
        self.pre = None
    
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        # # 递归,按照先序遍历的倒序进行遍历,处理根节点时,把左节点置 None,右节点置为 pre,更新 pre
        # if not root:
        #     return
        # self.flatten(root.right)
        # self.flatten(root.left)
        # # 处理根节点
        # root.left = None
        # root.right = self.pre
        # self.pre = root
        # return

        # 迭代,找到左子树最右节点pre,把右子树接到 pre 右节点上,左子树放到右子树,左子树置 None
        while root:
            if not root.left:
                root = root.right
                continue
            # 找到左子树最右节点pre
            pre = root.left
            while pre.right:
                pre = pre.right
            pre.right = root.right  # 右子树接到 pre 右节点上
            root.right = root.left  # 左子树放到右子树
            root.left = None  # 左子树置 None

116. 填充每个节点的下一个右侧节点指针

"""
# 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: 'Optional[Node]') -> 'Optional[Node]':
        # # BFS 层序遍历
        # if not root:
        #     return None
        # level = 0
        # queue = [root]
        # while len(queue):
        #     size = len(queue)
        #     while size:
        #         cur = queue.pop(0)
        #         # 填充逻辑
        #         if cur and size > 1:
        #             cur.next = queue[0]
        #         #
        #         if cur.left:
        #             queue.append(cur.left)
        #         if cur.right:
        #             queue.append(cur.right)
        #         size -= 1
        #     level += 1
        # return root

        # 层序遍历,第 N 层处理第 N+1 层连接
        if not root:
            return None
        # 最左侧节点,表示该层开始
        left_most = root
        # 只要下一层有节点,就遍历
        while left_most.left:
            # 遍历第 N 层节点
            head = left_most
            while head:
                # 连接左节点和右节点
                head.left.next = head.right
                # 连接右节点和下一个的左节点
                if head.next:
                    head.right.next = head.next.left
                # 第 N 层 下一个节点
                head = head.next
            left_most = left_most.left
        return root

129. 求根节点到叶节点数字之和

# 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 __init__(self):
        self.res = 0
        self.ans = 0
    
    def sumNumbers(self, root: TreeNode) -> int:
        # # dfs, 回溯,记录所有根节点到叶节点路径,同时计算路径数字
        # if not root:
        #     return 0
        # def dfs(node):
        #     self.ans = self.ans * 10 + node.val
        #     # 截止条件
        #     if not node.left and not node.right:
        #         self.res += int(self.ans)
        #         return
        #     # 做选择
        #     if node.left:
        #         dfs(node.left)
        #         # 退出选择
        #         self.ans = (self.ans - node.left.val) / 10
        #     if node.right:
        #         dfs(node.right)
        #         # 退出选择
        #         self.ans = (self.ans - node.right.val) / 10
        # dfs(root)
        # return self.res

        # dfs 遍历一遍节点
        if not root:
            return self.res
        def dfs(node, preSum):
            # 截止条件
            if not node:
                return
            # 计算该节点对应的数字
            preSum = preSum * 10 + node.val
            # 判断是否叶子节点,加到 result 中
            if not node.left and not node.right:
                self.res += preSum
            # 递归左右节点
            dfs(node.left, preSum)
            dfs(node.right, preSum)
        dfs(root, 0)
        return self.res

130. 被围绕的区域

class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        # dfs,遍历边界字符,深度递归,找到所有与边界相连的‘O’,标记
        # 重新遍历整个数组,替换未被标记的‘O’
        m = len(board)
        n = len(board[0])

        def dfs(i, j):
            # 边界条件
            if i >= m or j >= n or i < 0 or j < 0 or board[i][j] != 'O':
                return
            # 标记
            board[i][j] = '1'
            # 寻找相邻字符‘O’
            dfs(i, j+1)
            dfs(i, j-1)
            dfs(i-1, j)
            dfs(i+1, j)
            return

        # 遍历第一行和最后一行,找到字符‘O’,进入递归,标记
        # 处理首尾行
        for j in range(0, n):
            dfs(0, j)
            dfs(m-1, j)
        # 处理首尾列
        for i in range(0, m-1):
            dfs(i, 0)
            dfs(i, n-1)
        # 标记结束,重新遍历,替换未被标记的‘O’
        for i in range(m):
            for j in range(n):
                if board[i][j] == '1':
                    board[i][j] = 'O'
                elif board[i][j] == 'O':
                    board[i][j] = 'X'
        return

144. 二叉树的前序遍历

# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # # 递归
        # res = []

        # def preorder(root):
        #     if not root:
        #         return
        #     res.append(root.val)
        #     preorder(root.left)
        #     preorder(root.right)

        # preorder(root)
        # return res

        # 迭代,借助一个 stack
        res = []
        stack = []
        if not root:
            return res
        stack.append(root)
        while len(stack):
            cur = stack.pop()
            res.append(cur.val)
            if cur.right:
                stack.append(cur.right)
            if cur.left:
                stack.append(cur.left)
        return res

145. 二叉树的后序遍历

# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # # 递归
        # res = []

        # def postorder(node):
        #     if not node:
        #         return
        #     postorder(node.left)
        #     postorder(node.right)
        #     res.append(node.val)
        
        # postorder(root)
        # return res

        # # 迭代,借助两个 stack,先根右左,再左右根
        # if not root:
        #     return []
        # res = []  # 存放顺序 左右根
        # stack1 = []
        # stack2 = []  # 存放顺序 根右左
        # stack1.append(root)
        # while len(stack1):
        #     cur = stack1.pop()
        #     stack2.append(cur.val)
        #     if cur.left:
        #         stack1.append(cur.left)
        #     if cur.right:
        #         stack1.append(cur.right)
        # while len(stack2):
        #     res.append(stack2.pop())
        # return res

        # 迭代
        if not root:
            return []
        res = []
        stack = []
        prev = None

        while root or len(stack):
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            # 判断右子树是否空 或者 是否已经访问过
            if not root.right or prev == root.right:
                res.append(root.val)
                prev = root
                root = None
            else:
                # 没访问过,继续访问右子树
                stack.append(root)
                root = root.right
        return res

199. 二叉树的右视图

# 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 rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        # 层次遍历,打印每层最后一个
        res = []
        if not root:
            return res
        queue = []
        queue.append(root)
        while len(queue):
            size = len(queue)
            while size:
                cur = queue.pop(0)
                # 是否是每层最后一个元素
                if size == 1:
                    res.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
                size -= 1
        return res

200. 岛屿数量

力扣

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        # dfs
        def dfs(i, j):
            # base case
            if not inArea(i, j):
                return
            grid[i][j] = 2  # 标记为已访问
            dfs(i-1, j)
            dfs(i+1, j)
            dfs(i, j-1)
            dfs(i, j+1)
            return
        
        def inArea(i, j):
            if i >=0 and j >= 0 and i < len(grid) and j < len(grid[0]) and grid[i][j] == '1':
                return True

        res = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    dfs(i, j)
                    res += 1
        return res

207. 课程表

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 广度优先搜索
        # 构建邻接表 & 入度数组
        course = [[] for _ in range(numCourses)]
        indegree = [0 for _ in range(numCourses)]
        for item in prerequisites:
            course[item[1]].append(item[0])
            indegree[item[0]] += 1
        
        # 选课队列,挑选入度为 0 入队
        queue = []
        for i in range(numCourses):
            if indegree[i] == 0:
                queue.append(i)
        
        # 选出一门课,遍历邻居,更新 indegree
        count = 0  # 选课数
        while len(queue):
            cur = queue.pop(0)
            count += 1
            for c in course[cur]:
                indegree[c] -= 1  # 更新入度
                if indegree[c] == 0:
                    queue.append(c)
        return count == numCourses

210. 课程表 II

class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        # 广度优先搜索
        # 构建邻接表 & 入度数组
        course = [[] for _ in range(numCourses)]
        indegree = [0 for _ in range(numCourses)]
        for item in prerequisites:
            course[item[1]].append(item[0])
            indegree[item[0]] += 1
        
        # 选课队列,挑选入度为 0 入队
        queue = []
        for i in range(numCourses):
            if indegree[i] == 0:
                queue.append(i)
        
        # 选出一门课,遍历邻居,更新 indegree
        res = []
        while len(queue):
            cur = queue.pop(0)
            res.append(cur)
            for c in course[cur]:
                indegree[c] -= 1  # 更新入度
                if indegree[c] == 0:
                    queue.append(c)
        if len(res) == numCourses:
            return res
        else:
            return []

222. 完全二叉树的节点个数

# 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 countNodes(self, root: TreeNode) -> int:
        # # 二分查找 找到最后一层节点个数
        # # 树的深度
        def getDepth(root):
            if not root:
                return 0
            return getDepth(root.left) + 1
        
        # def isExist(root, index, depth):
        #     while depth > 1:
        #         mid = (1 << (depth-1)) // 2
        #         if index < mid:
        #             root = root.left
        #         else:
        #             index -= mid
        #             root = root.right
        #         depth -= 1
        #     return root != None
        
        # if not root:
        #     return 0
        # depth = getDepth(root)
        # count1 = (1 << (depth-1)) - 1
        # # 二分查找最后一个节点索引
        # start = 0
        # end = count1
        # while start <= end:
        #     mid = start + (end - start) // 2
        #     if isExist(root, mid, depth):
        #         start = mid + 1
        #         print(start)
        #     else:
        #         end = mid - 1
        # return count1 + start

        # 空树,节点数为 0
        if root == None:
            return 0
        # 求左子树和右子树的深度
        leftHeight = getDepth(root.left)
        rightHeight = getDepth(root.right)
        
        # 如果左子树的深度 = 右子树的深度,左子树为满二叉树
        # 节点数 = 左子树的深度 + 右子树的深度 + 根节点
        if leftHeight == rightHeight:
            return (2 ** leftHeight - 1) + self.countNodes(root.right) + 1
        # 如果左子树的深度 > 右子树的深度,右子树为满二叉树
        # 节点数 = 左子树的深度 + 右子树的深度 + 根节点
        else:
            return (2 ** rightHeight - 1) + self.countNodes(root.left) + 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值