当前位置: 首页 > news >正文

Leetcode 437 -- dfs | 前缀和

题目描述

路径总和

思路

由于题目的范围较小,所有点的个数小于一千,因此我们可以暴力 d f s dfs dfs 套$ dfs$,以每一个节点作为根节点,然后向下遍历求每一个节点到该节点的路径和,时间复杂度为 O ( N 2 ) O(N^2) O(N2)
但这种做法肯定会有大量重复计算,那么有没有什么办法可以消除这些重复计算呢?

我们想一下,在暴力 d f s dfs dfs 套$ dfs$中,我们的每个节点都会计算出每一个下层节点到该节点的路径和,那么当我们遍历到下层节点的时候,有没有什么办法可以利用这些上层节点已经计算完的数据呢?
例如下图:

                     1/ 2    / 3   / 4  

当我们遍历到节点 4 4 4 的时候,我们是可以得到节点 1 1 1 到节点 2 , 3 , 4 2,3,4 2,3,4 和节点 2 2 2 到节点 3 , 4 3, 4 3,4 以及节点 3 3 3 到节点 4 4 4 的路径之和的,问题是该怎么利用?
想要利用这些数据,我们就不能再从根节点往下找路径和,为什么?
如果我们从根节点往下找路径和,那么上层节点是什么样与我们根本就没有关系,我们只关心下层节点是什么样子的。
因此,我们需要转换思路,求每个根节点到它上层所有节点的路径之和,这样,我们就可以利用这些上层节点已经计算完的数据了。

问题来了,该怎么利用?
在思考这个问题之前,你应该发现,这些数据其实就是以每一个节点作为根节点求得的到其下层节点的前缀和
因此我们只需要将这些信息用一个数据结构保存起来即可!
现在,走到节点 4 4 4 的时候,路径和为 1 + 2 + 3 + 4 = 10 1+2+3+4=10 1+2+3+4=10,此时如果存在路径和等于 t a r g e t S u m − 10 targetSum-10 targetSum10,那么就存在节点 4 4 4 到上层某个节点的一条符合要求的路径和。
并且这条路径肯定是和节点 4 4 4 联通的,因为我们去掉的是由根节点 1 1 1 到某个节点 x x x 的路径,得到的是节点 x x x 到节点 4 4 4 的路径。

所以说,我们前缀和的定义为:根节点到每个下层节点的前缀和。
注意这个根节点是最顶层的根节点,而不是将每一个节点都视为根节点,因为我们只需要知道最顶层的根节点到每一个节点的前缀和就可以找到某一个节点到任意上层节点的前缀和,通过减法。
另外,我们还需要记录某一个前缀和的个数,因为节点的值可能为 0 0 0
另外一些细节见代码。

代码–前缀和

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:unordered_map<long long, int> prefix;   // <前缀和, 个数>int dfs(TreeNode *root, long long curSum, int targetSum){if(root == NULL)    return 0;int ans = 0;curSum += root->val;if(prefix.count(curSum - targetSum))    // 不存在时不会创建对象ans = prefix[curSum - targetSum]; // 上层是否存在前缀和[curSum-trgetSum]// 题目规定,路径和之能往下走,所以说我们需要回溯 prefix 的值,否则就会出现往上走的情况prefix[curSum] ++ ;ans += dfs(root->left, curSum, targetSum);ans += dfs(root->right, curSum, targetSum);prefix[curSum] -- ;return ans;}int pathSum(TreeNode* root, int targetSum) {if(root == NULL)    return 0;prefix[0] = 1;      // 初始化前缀和return dfs(root, 0, targetSum);}
};

http://www.mrgr.cn/news/97080.html

相关文章:

  • centos8上实现lvs集群负载均衡dr模式
  • swift-oc和swift block和代理
  • Dive into Deep Learning - 2.4. Calculus (微积分)
  • 如何实现浏览器中的报表打印
  • yolov12检测 聚类轨迹运动速度
  • 【小沐杂货铺】基于Three.JS绘制太阳系Solar System(GIS 、WebGL、vue、react)
  • Vanna:用检索增强生成(RAG)技术革新自然语言转SQL
  • #SVA语法滴水穿石# (002)关于 |-> + ##[min:max] 的联合理解
  • JAVA线程安全
  • orangepi zero烧录及SSH联网
  • c++项目 网络聊天服务器 实现
  • Neo4j操作数据库(Cypher语法)
  • Java 大视界 -- 基于 Java 的大数据机器学习模型在图像识别中的迁移学习与模型优化(173)
  • Linux线程同步与互斥:【线程互斥】【线程同步】【线程池】
  • leetcode117 填充每个节点的下一个右侧节点指针2
  • hackmyvm-Principle
  • 《概率论与数理统计》期末复习笔记_下
  • QGIS实战系列(六):进阶应用篇——Python 脚本自动化与三维可视化
  • AI医疗诊疗系统设计方案
  • 《概率论与数理统计》期末复习笔记_上