Path Sum III
问题描述:给定一颗二叉树,计算有多少条路径的sum等于一个target。路径的定义为从起点和终点之间依次都满足是后者是前者的孩子。如下图所示: 问题分析:
针对每个节点,我们可以记录从跟节点到该节点所经历的所有value -> paths。 然后我们计算该点和前面所有点的value和等于sum的个数。 同样的我们递归计算该点的左孩子,右孩子。 最终的结果等于cur + left + right 是否可以优化?
因为我们针对每个点,都要遍历一边paths,path 的长度取决于该点和root之间的距离。 我们能否将value记忆起来?来免去这次遍历。 我们知道最终的目标是找到一段路径的和为S。那么我们假设从跟节点到当前节点的和为X。则经过包含该点的路径的个数就等于从root遍历到目前这个点有多少和点对应的和为X-S。 我们可以用map来记录这些值。map<key, value>, 表示从跟节点开始计算和为key的所有点的个数value。 注意,在结束该点的遍历的时候,对应的map的记录也要减去1. 代码
#include <vector>
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
class Solution {
public:
unordered_map< int , int > shown;
int exisitSolution ( vector< int > paths, int cur_ele, int sum) {
int res = 0 ;
for ( int i= paths. size ( ) - 1 ; i>= 0 ; i-- ) {
cur_ele + = paths[ i] ;
if ( cur_ele == sum)
res + = 1 ;
}
return res;
}
int pathSumCore ( TreeNode* root, int sum, vector< int > paths) {
if ( root == NULL )
return 0 ;
int cur = exisitSolution ( paths, root-> val, sum) ;
if ( root-> val == sum) {
cur + = 1 ;
}
paths. push_back ( root-> val) ;
int left = pathSumCore ( root-> left, sum, paths) ;
int right = pathSumCore ( root-> right, sum, paths) ;
return left + right + cur;
}
int pathSumCoreV2 ( TreeNode* root, int sum, int pre_sum) {
if ( root == NULL )
return 0 ;
pre_sum + = root-> val;
int cur = shown[ pre_sum - sum] ;
shown[ pre_sum] = shown[ pre_sum] + 1 ;
int left = pathSumCoreV2 ( root-> left, sum, pre_sum) ;
int right = pathSumCoreV2 ( root-> right, sum, pre_sum) ;
shown[ pre_sum] - = 1 ;
return cur + left + right;
}
int pathSum ( TreeNode* root, int sum) {
shown[ 0 ] = 1 ;
return pathSumCoreV2 ( root, sum, 0 ) ;
}
static void solution ( ) {
Solution solution1;
TreeNode* root = TreeNode: : buildByLevel ( { 1 , 0 , 1 , 1 , 2 , 0 , - 1 , 0 , 1 , - 1 , 0 , - 1 , 0 , 1 , 0 } , - 5 ) ;
TreeNode: : levelOrder ( root) ;
cout<< solution1. pathSum ( root, 2 ) << endl;
}
} ;