力扣hot100 路径总和Ⅲ dfs 前缀和 一题双解 超全注释

Problem: 437. 路径总和 III

思路

树的遍历 + DFS

一个朴素的做法是搜索以每个节点为根的(往下的)所有路径,并对路径总和为 targetSumtargetSumtargetSum 的路径进行累加统计。
使用 dfs1 来搜索所有节点,复杂度为 O(n)O(n)O(n);在 dfs1 中对于每个当前节点,使用 dfs2 搜索以其为根的所有(往下的)路径,同时累加路径总和为 targetSumtargetSumtargetSum 的所有路径,复杂度为 O(n)O(n)O(n)。

👨‍🏫 参考题解

💖 树的遍历 + dfs

时间复杂度, 示例: O ( n 2 ) O(n^2) O(n2)

Java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
	long ans, t;// ans 统计符合要求的路径数量,t 记录目标值

	public int pathSum(TreeNode root, int targetSum)
	{
		t = targetSum;
		dfs1(root);
		return (int) ans;

	}

//	遍历 root 的所有子结点
	private void dfs1(TreeNode root)
	{
		if (root == null)
			return;
		dfs2(root, root.val);
		dfs1(root.left);
		dfs1(root.right);
	}

//	以 root 为根遍历其所有合法路径
	private void dfs2(TreeNode root, long val)
	{
		if (val == t)// 如果当前路径和恰好 == 目标值 ans++
			ans++;
		if (root.left != null)// 向左子树延申路径
			dfs2(root.left, val + root.left.val);
		if (root.right != null)// 向右子树延申路径
			dfs2(root.right, val + root.right.val);
	}
}

💖 树的遍历 + 前缀和

👨‍🏫 参考题解

时间复杂度, 示例: O ( n ) O(n) O(n)
从根节点到每个叶子结点的路径唯一,这就是一个前缀和

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
	long ans, t;// ans 统计符合要求的路径数量,t 记录目标值

//	注意:map集合只会包含当前结点的 祖先结点 的前缀和(在递归的过程种进行恢复现场)
	Map<Long, Integer> map = new HashMap<>();// key是前缀和,value是前缀和为key的结点数量

	public int pathSum(TreeNode root, int target)
	{
		if (root == null)
			return 0;
		t = target;
		map.put(0L, 1);
		dfs(root, root.val);
		return (int) ans;
	}

	/**
	 * @param root 当前根节点
	 * @param val  以当前root为尾结点的前缀和(此值唯一)
	 */
	private void dfs(TreeNode root, long val)
	{
		// 当前点前缀和(val) - 前边点的前缀和(map的key) == t
		// key = val - t,此 key 存在,证明前缀和可以实现
		if (map.containsKey(val - t))
			ans += map.get(val - t);
		map.put(val, map.getOrDefault(val, 0) + 1);//把当前点的前缀和作为 key 存进 map中
//		递归遍历当前树的左右子树
		if (root.left != null)
			dfs(root.left, val + root.left.val);
		if (root.right != null)
			dfs(root.right, val + root.right.val);
//		把当前点的前缀和作为 key 从 map 中取出,因为上边两个递归已经把它的子树(后代节点)都处理完了(留着也没用)
//		恢复现场:当前分支产生的影响不应该干扰到当前结点的兄弟分支的结果
		map.put(val, map.getOrDefault(val, 0) - 1);
	}
}
相关推荐
草履虫建模5 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq7 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq8 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
爱吃rabbit的mq8 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)9 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi9 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱10 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头10 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头10 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机
咖丨喱12 小时前
IP校验和算法解析与实现
网络·tcp/ip·算法