路径总和 II
题目描述:
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5 输出:[]
示例 3:
输入:root = [1,2], targetSum = 0 输出:[]
链接:
113. 路径总和 II - 力扣(LeetCode) (leetcode-cn.com)
解题思路
思路一:深度优先搜索
枚举每一条从根节点到叶子节点的路径。当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {number[][]}
*/
var pathSum = function (root, targetSum) {
var result = [], stack = [];
if (root === null) {
return result;
}
var dfs = function (root) {
if (root == null) {
return;
}
stack.push(root.val);
// 到了叶子节点并且和等于targetSum时添加到结果集
if (root.left === null && root.right === null) {
var sum = 0;
for (var i in stack) {
sum += stack[i];
}
sum === targetSum && result.push(stack.slice(0));
}
// 递归遍历左右子树
dfs(root.left);
dfs(root.right);
// 回溯
stack.pop();
}
dfs(root);
return result;
};
时间复杂度: O(n^2),其中 n 是二叉树中的节点个数
在最坏情况下,树的上半部分为链状,下半部分为完全二叉树,并且从根节点到每一个叶子节点的路径都符合题目要求。此时,路径的数目为 O(n),并且每一条路径的节点个数也为 O(N),因此要将这些路径全部添加进答案中,时间复杂度为 O(n^2)
空间复杂度: O(n)
思路二:广度优先搜索
为了节省空间,我们使用哈希表记录树中的每一个节点的父节点。每次找到一个满足条件的节点,我们就从该节点出发不断向父节点迭代,即可还原出从根节点到当前节点的路径。
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {number[][]}
*/
var pathSum = function (root, targetSum) {
let res = [];
let map = new Map();
// 通过底下叶子节点 获得从叶子节点到根节点的路径
const getPath = (node) => {
let path = [];
while (node != null) {
path.push(node.val);
// 向上找它的父节点
node = map.get(node);
}
path.reverse();
return path;
};
const bfs = (root, sum) => {
// 队列中每一个元素包含 节点 节点及路过路径上的值的和
let queue = [[root, sum]];
while (queue.length) {
let [node, sum] = queue.shift();
// 如果是叶子节点并且 路径总和已经等于目标值了
if (node.left == null && node.right == null && sum == targetSum) {
res.push(getPath(node));
} else {
if (node.left) {
queue.push([node.left, node.left.val + sum]);
// map里面存的key是子节点 value是父节点 这样方便向上查找路径
map.set(node.left, node);
}
if (node.right) {
queue.push([node.right, node.right.val + sum]);
map.set(node.right, node);
}
}
}
};
if (root == null) return [];
// 节点 节点及路过路径上的值的和
bfs(root, root.val);
return res;
};