【leetcode】437. 路径总和 III

66 阅读2分钟

leetcode-437.png

这一题比较明显的需要使用dfs来解决

错误代码

这里的代码没有考虑到每个节点开始遍历的情况

var pathSum = function (root, targetSum) {
    let cnt = 0
    var dfs = function (node, sum) {
        if (!node) return
        if (sum === targetSum) {
            cnt++
            sum = 0
        }
        dfs(node?.left, node?.val + sum)
        dfs(node?.right, node?.val + sum)
    }
    dfs(root, 0)
    return cnt
};

正确代码

  1. DFS (深度优先搜索)
    • dfs 函数从当前节点开始,计算从该节点出发的路径和是否等于 targetSum
    • 如果路径和等于 targetSum,则计数器 count 增加。
    • 然后递归检查左子树和右子树。
  2. 遍历整个树
    • traverse 函数从树的每个节点开始调用 dfs,确保我们从每个节点出发都进行了路径和的检查。
    • 这样可以确保所有路径都被遍历到,不遗漏任何可能的路径。
  3. 计数器
    • 最后返回计数器 count,它包含所有路径和等于 targetSum 的路径数量。 这种方法的时间复杂度是 O(n^2),因为每个节点都要作为起点进行一次 DFS 搜索,但对于一般的树结构来说,这种方法是可行的。
var pathSum = function (root, targetSum) {
    let cnt = 0
    var dfs = function (node, sum) {
        if (!node) return
        sum += node.val
        if (sum === targetSum) {
            cnt++
        }
        dfs(node.left, sum)
        dfs(node.right, sum)
    }
    // 测试每一个节点
    var traverse = function(node){
        if(!node) return 
        dfs(node, 0)
        traverse(node.left)
        traverse(node.right)
    }
    traverse(root)
    return cnt
};

前缀和解法

  • 前缀和

    • currentSum 记录当前路径的前缀和。
    • 如果在当前路径上存在一个前缀和等于 currentSum - targetSum,说明从该前缀和到当前节点的路径和为 targetSum
  • 哈希表 map

    • 这个哈希表用来存储每个前缀和出现的次数。
    • 通过查找 currentSum - targetSum 是否在哈希表中存在,可以快速判断是否有符合条件的路径。
    • 每次递归调用后,当前节点的前缀和计数会增加或减少,以保证每条路径计算的独立性。
  • 回溯

    • 当从子节点返回时,需要恢复当前节点的前缀和计数,即从哈希表中减去当前节点的贡献,以便不影响其他路径的计算。
  • 时间复杂度

    • 该方法的时间复杂度是 O(n),因为每个节点只被访问一次,且哈希表的操作都是常数时间。
var pathSum = function (root, targetSum) {
    let cnt = 0
    let map = new Map()
    map.set(0, 1)
    var dfs = function (node, currentSum) {
        if (!node) return
        currentSum += node.val
        if (map.has(currentSum - targetSum)) {
            cnt += map.get(currentSum - targetSum)
        }
        map.set(currentSum, (map.get(currentSum) || 0) + 1)
        dfs(node.left, currentSum)
        dfs(node.right, currentSum)
        map.set(currentSum, map.get(currentSum) - 1)
    }
    dfs(root, 0)
    return cnt
};