我理解的三种经典排序算法

web自动化——pytest概念

  返回  

LeetCode《程序员面试金典》面试题 04.12. 求和路径

2021/8/21 18:20:09 浏览:

LeetCode 面试题 04.12. 求和路径

  • 题目
  • 解题
    • 解题一:蛮力法
    • 解题二:优化算法

题目

在这里插入图片描述
路径不一定非得从二叉树的根节点或叶节点开始或结束
但是其方向必须向下 (只能从父节点指向子节点方向) 且 路径是连续的

解题

解题一:蛮力法

在蛮力法中,我们只需查看所有可能的路径。为此,遍历每个节点,对于每个节点,用递归法尝试所有向下的路径,并随着递归的进行跟踪路径的和。每当得到目标和,将发现的路径数目加一。

// javascript
var pathSum = function(root, sum) {
    if (root == null) return 0;
    // 对从 root 开始,符合目标和的路径进行计数
    let pathsFromRoot = countPathsWithSumFromNode(root, sum);
    // 尝试左节点和右节点
    let pathsOnLeft = pathSum(root.left, sum);
    let pathsOnRight = pathSum(root.right, sum);
    return pathsFromRoot + pathsOnLeft + pathsOnRight;
};

// 返回从该节点开始,符合目标和的路径的条数
var countPathsWithSumFromNode = function(node, targetSum) {
    if (node == null) return 0;
    let totalPaths = 0;
    if (node.val === targetSum) { // 找到一条从 root 开始的路径
        totalPaths++;
    }
    totalPaths += countPathsWithSumFromNode(node.left, targetSum - node.val);
    totalPaths += countPathsWithSumFromNode(node.right, targetSum - node.val);
    return totalPaths;
};

在这里插入图片描述
在这里插入图片描述

解题二:优化算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// javascript
var pathSum = function(root, sum) {
    return countPathWithSum(root, sum, 0, new Map());
};

var countPathWithSum = function(root, targetSum, cumSum, record) {
    if (root === null) return 0; // 基础情况
    
    cumSum += root.val;
    let sum = cumSum - targetSum;
 	// 对终止于该节点,符合目标和的路径进行计数
    // let totalPaths = record[sum] ? record[sum] : 0;
    let totalPaths = record.has(sum) ? record.get(sum) : 0;

	// 如果 runningSum 等于 targetSum,则发现一条从 root 开始的新路径。加上这条路径
    if (cumSum === targetSum) totalPaths++;

	// 对 pathCount 加 1,递归,对 pathCount 减 1
    increateHashTable(record, cumSum, 1);
    totalPaths += countPathWithSum(root.left, targetSum, cumSum, record);
    totalPaths += countPathWithSum(root.right, targetSum, cumSum, record);
    increateHashTable(record, cumSum, -1);
    return totalPaths;
}

var increateHashTable = function(record, cumSum, delta) {
    // if (record[cumSum]) record[cumSum] += delta;
    if (record.has(cumSum) === true) record.set(cumSum, record.get(cumSum) + delta);
    // else record[cumSum] = delta;
    else record.set(cumSum, delta);
    // if (record[cumSum] === 0) record.delete(cumSum);
    if (record.get(cumSum) === 0) record.delete(cumSum);
}

空间复杂度为 O ( l o g N ) O(log N) O(logN),是因为每处理完一个节点会进行回溯,如果散列表中 cumSum 对应的值为0,会将这条记录删除。

特别注意要进行 回溯,比如 root = [0, 1, 1] sum = 0: 如果 0.left (1) 不进行回溯,0.right (1) 会找到 record[1] = 1,totalPaths 会首先获得初始值 1,这是不对的。
在这里插入图片描述
另外,在 js 中:

  1. has 要搭配 getset 使用,假设是用 record[0] = 1record.has(0)false,应该用 if (record[0]) 进行判断;
  2. record[0] = 1 设置值时,如果用 for (let key in record) 来遍历,key 的类型是 字符串,如果要进行加法运算,比如 let newKey = key + 1,应该写成 let newKey = key - 0 + 1。因为 字符串加法会隐式转换后面的值,最后变成字符串拼接

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号