LeetCode题目112:多种算法实现路径总与改进过程

简介: LeetCode题目112:多种算法实现路径总与改进过程

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。

会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区:码上找工作

作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

python数据分析可视化:企业实战案例

python源码解读

程序员必备的数学知识与应用

题目描述

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

示例

示例

输入:

5
   / \
  4   8
 /   / \
11  13  4
/ \      \
7   2      1

目标和 = 22

输出:True(存在路径 5 -> 4 -> 11 -> 2,和为 22)

方法一:递归深度优先搜索(DFS)

解题步骤
  1. 递归函数定义:定义一个辅助函数来递归检查每个节点,传递当前的累计总和。
  2. 递归终止条件:如果当前节点是叶子节点,并且其值加上累计总和等于目标值,返回 True
  3. 递归逻辑:递归检查当前节点的左右子节点。
Python 示例
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
def hasPathSum(root, sum):
    """
    检查二叉树中是否存在根到叶子的路径总和等于给定值
    :param root: TreeNode, 二叉树的根节点
    :param sum: int, 目标和
    :return: bool
    """
    if not root:
        return False
    sum -= root.val
    if not root.left and not root.right:  # 检查是否为叶子节点
        return sum == 0
    return hasPathSum(root.left, sum) or hasPathSum(root.right, sum)
算法分析
  • 时间复杂度:(O(n)),每个节点访问一次。
  • 空间复杂度:(O(h)),递归栈的深度,其中 (h) 是树的高度。

方法一使用递归深度优先搜索(DFS)来寻找是否存在从根到叶子的路径,其和等于给定的目标值。虽然这种方法直观且易于实现,但在某些情况下可能会进行不必要的递归调用,尤其是在不平衡的树中。因此,我们可以通过一些技术改进它,以提高效率和实用性。

方法一改进:优化的递归DFS

改进点
  1. 短路逻辑:在递归过程中,一旦找到符合条件的路径,即可立即停止进一步的递归,避免不必要的计算。
  2. 减少参数传递:可以通过直接修改传递的 sum 参数来减少参数的数量,这样可以稍微降低递归调用的开销。
改进后的 Python 示例
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
def hasPathSum(root, sum):
    """
    使用优化的DFS检查是否存在从根到叶的路径总和等于给定值
    :param root: TreeNode, 二叉树的根节点
    :param sum: int, 目标和
    :return: bool
    """
    if not root:
        return False
    # 检查是否到达叶子节点并且路径总和匹配
    if not root.left and not root.right:
        return root.val == sum
    # 递归检查左右子树
    sum -= root.val
    return hasPathSum(root.left, sum) or hasPathSum(root.right, sum)
# 示例调用
root = TreeNode(5, TreeNode(4, TreeNode(11, TreeNode(7), TreeNode(2)), None), TreeNode(8, TreeNode(13), TreeNode(4, None, TreeNode(1))))
print(hasPathSum(root, 22))  # 输出: True
算法分析
  • 时间复杂度:改进后,时间复杂度依然为 (O(n)),因为每个节点仍然需要至多被访问一次。
  • 空间复杂度:改进后,空间复杂度也为 (O(h)),其中 (h) 是树的高度,对应于递归栈的最大深度。通过短路逻辑,可能在找到第一个有效路径时减少空间使用。
优劣势比较
  • 优点
  • 短路逻辑可以减少在找到有效路径后的不必要递归,提高效率。
  • 直接修改 sum 减少了参数传递,稍微优化了递归的性能。
  • 缺点
  • 递归深度依然依赖于树的高度,对于极端不平衡的树依然可能导致较高的空间复杂度。

这种改进使得递归方法在实际应用中更加高效,尤其是在早期找到符合条件的路径时,能够显著减少计算量。

方法二:迭代使用栈

解题步骤
  1. 使用栈:利用栈存储每个节点及其对应的路径总和。
  2. 迭代逻辑:迭代访问每个节点,更新路径总和,检查叶子节点的路径总和。
Python 示例
def hasPathSum(root, sum):
    if not root:
        return False
    stack = [(root, root.val)]
    while stack:
        node, curr_sum = stack.pop()
        if not node.left and not node.right and curr_sum == sum:
            return True
        if node.right:
            stack.append((node.right, curr_sum + node.right.val))
        if node.left:
            stack.append((node.left, curr_sum + node.left.val))
    return False
算法分析
  • 时间复杂度:(O(n)),每个节点最多被访问一次。
  • 空间复杂度:(O(n)),在最坏的情况下,栈中需要存储所有节点。

方法二使用迭代的方式通过栈实现深度优先搜索(DFS),检查是否存在从根到叶的路径,其和等于给定目标值。虽然迭代方法减少了递归可能引起的栈溢出问题,但其管理栈的方式仍有改进空间,特别是在如何更高效地处理节点和路径和的记录。

方法二改进:优化的迭代DFS

改进点
  1. 使用结构体或类:为了减少重复的元素推入和弹出操作,可以创建一个简单的类或结构体来存储节点以及到该节点为止的累积和,这样可以使代码更加清晰且减少错误。
  2. 早停机制:在发现第一个符合条件的叶子节点时立即停止所有操作,避免不必要的迭代。
改进后的 Python 示例
from collections import deque
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class PathNode:
    def __init__(self, node, current_sum):
        self.node = node
        self.current_sum = current_sum
def hasPathSum(root, targetSum):
    if not root:
        return False
    stack = deque([PathNode(root, root.val)])  # 使用PathNode来存储节点和当前路径和
    while stack:
        path_node = stack.pop()
        node = path_node.node
        current_sum = path_node.current_sum
        # 检查是否到达叶子节点且路径和符合条件
        if not node.left and not node.right and current_sum == targetSum:
            return True
        # 将非空子节点和相应的路径和压入栈
        if node.right:
            stack.append(PathNode(node.right, current_sum + node.right.val))
        if node.left:
            stack.append(PathNode(node.left, current_sum + node.left.val))
    return False
# 示例调用
root = TreeNode(5, TreeNode(4, TreeNode(11, TreeNode(7), TreeNode(2)), None), TreeNode(8, TreeNode(13), TreeNode(4, None, TreeNode(1))))
print(hasPathSum(root, 22))  # 输出: True
算法分析
  • 时间复杂度:优化后,时间复杂度仍为 (O(n)),每个节点最多被访问一次。
  • 空间复杂度:优化后,空间复杂度也为 (O(n)),在最坏的情况下可能需要存储所有节点。
优劣势比较
  • 优点
  • 代码结构更清晰,通过使用 PathNode 类减少了代码的复杂度和出错概率。
  • 早停机制提高了效率,避免了不必要的迭代。
  • 缺点
  • 空间复杂度相比递归方法有所提高,因为迭代方法需要显式使用栈存储节点。

通过这种改进,迭代方法在处理大型数据集时更加健壮且易于维护,尤其适用于深度较大的树结构,减少了递归可能导致的栈溢出风险。

应用示例

这些方法在计算机科学中广泛应用于路径查找、网络流量分析、资源管理等领域,其中需要确定从一个点到另一个点的可达性或路径成本。


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
6月前
|
存储 算法
算法入门:专题二---滑动窗口(长度最小的子数组)类型题目攻克!
给定一个正整数数组和目标值target,找出总和大于等于target的最短连续子数组长度。利用滑动窗口(双指针)优化,维护窗口内元素和,通过单调性避免重复枚举,时间复杂度O(n)。当窗口和满足条件时收缩左边界,更新最小长度,最终返回结果。
|
7月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
343 3
|
6月前
|
机器学习/深度学习 算法 C++
【DFS/回溯算法】2016年蓝桥杯真题之路径之谜详解
题目要求根据城堡北墙和西墙箭靶上的箭数,推断骑士从西北角到东南角的唯一路径。每步移动时向正北和正西各射一箭,同一格不重复经过。通过DFS回溯模拟“拔箭”过程,验证路径合法性。已知箭数约束路径唯一,最终按编号输出行走顺序。
|
8月前
|
算法 机器人 定位技术
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
268 0
|
6月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
7月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
513 2
|
7月前
|
机器学习/深度学习 传感器 算法
基于全局路径的无人地面车辆的横向避让路径规划研究[蚂蚁算法求解](Matlab代码实现)
基于全局路径的无人地面车辆的横向避让路径规划研究[蚂蚁算法求解](Matlab代码实现)
343 8
|
7月前
|
算法 数据挖掘 区块链
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
217 2
|
6月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
7月前
|
机器学习/深度学习 负载均衡 算法
【卡车和无人机协同配送路径优化】遗传算法求解利用一辆卡车和两架无人机配合,将小包裹递送给随机分布的客户,以使所有站点都由卡车或无人机递送一次后返回起始位置(中转站)研究(Matlab代码实现)
【卡车和无人机协同配送路径优化】遗传算法求解利用一辆卡车和两架无人机配合,将小包裹递送给随机分布的客户,以使所有站点都由卡车或无人机递送一次后返回起始位置(中转站)研究(Matlab代码实现)
437 7

热门文章

最新文章