给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
方法1:简单的dfs即可
方法2:迭代。
用先序遍历,但是遍历到的每个节点它的左右子结点都需要加上其父结点值,再压入栈中。这样当遍历到叶结点时,如果和sum相等了,那么就说明一定有一条从root过来的路径。
// dfs
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if(root==nullptr)
return false;
return dfs(root,0,sum);
}
bool dfs(TreeNode* root,int cur,int target){
if(root==nullptr)
return false;
cur += root->val;
// 是叶节点且路径总和等于target
if(root->left==nullptr && root->right==nullptr && cur==target)
return true;
return dfs(root->left,cur,target) || dfs(root->right,cur,target);
}
};
// 迭代 先序遍历
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if (!root) return false;
stack st{{root}};
while (!st.empty()) {
TreeNode *t = st.top(); st.pop();
if (!t->left && !t->right) {
if (t->val == sum) return true;
}
if (t->right) {
t->right->val += t->val;
st.push(t->right);
}
if (t->left) {
t->left->val += t->val;
st.push(t->left);
}
}
return false;
}
};
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
dfs
class Solution {
public:
vector> pathSum(TreeNode* root, int sum) {
if(root==nullptr)
return {};
vector> res;
vector out;
dfs(root,0,sum,res,out);
return res;
}
void dfs(TreeNode *root, int cur,int target,vector> &res,vector &out){
if(root==nullptr)
return;
cur += root->val;
out.push_back(root->val);
if(!root->left && !root->right && cur==target){
res.push_back(out);
}
dfs(root->left,cur,target,res,out);
dfs(root->right,cur,target,res,out);
out.pop_back();
}
};
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
方法1: 先序遍历每个节点,求以每个节点为根(也就是起点)的符合条件的路径 (第n层节点会被遍历n次)
方法2:还是先序遍历每个节点,但这次计算以每个节点为终点的,所有符合路径的值,而该路径上的前缀和用哈希表来存
(每个节点只需要遍历1次)
//先序遍历每个节点,但这次计算以每个节点为终点的,所有符合路径的值
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if(!root)
return 0;
int res=0;
unordered_map pre;
pre[0]=1; // 为了下面 res += pre【cur-target】的统一性
dfs(root,0,sum,pre,res);
return res;
}
// 依旧先序遍历每个节点,但是这次遍历到每个节点的时候,求以该节点为终点的,所有符合路径的值
// 而前缀和通过pre来存储,相当于用空间换了时间
void dfs(TreeNode* root,int cur,int target,
unordered_map & pre,int &res){
if(!root)
return;
cur += root->val;
res += pre[cur-target]; // res += (pre.count(cur-target)?pre[cur-target]:0);
++pre[cur];
dfs(root->left,cur,target,pre,res);
dfs(root->right,cur,target,pre,res);
--pre[cur];
/*
if(pre[cur]==0)
pre.erase(cur);
*/
}
};
// 一开始的代码
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if(!root)
return 0;
int res=0;
helper(root,sum,res);
return res;
}
//先序遍历每个节点,dfs求 以每个节点为根的符合要求的路径
void helper(TreeNode* root,int target,int &res){
if(!root)
return;
dfs(root,0,target,res);
helper(root->left,target,res);
helper(root->right,target,res);
}
void dfs(TreeNode* root,int cur,int target,int &res){
if(!root)
return;
cur += root->val;
if(cur==target)
++res;
dfs(root->left,cur,target,res);
dfs(root->right,cur,target,res);
}
};
对于一棵深度小于 5 的树,可以用一组三位十进制整数来表示。
对于每个整数:
百位上的数字表示这个节点的深度 D,1 <= D <= 4。
十位上的数字表示这个节点在当前层所在的位置 P, 1 <= P <= 8。位置编号与一棵满二叉树的位置编号相同。
个位上的数字表示这个节点的权值 V,0 <= V <= 9。
给定一个包含三位整数的升序数组,表示一棵深度小于 5 的二叉树,请你返回从根到所有叶子结点的路径之和。
样例 1:
输入: [113, 215, 221]
输出: 12
解释:
这棵树形状如下:
3
/ \
5 1
路径和 = (3 + 5) + (3 + 1) = 12.
虽然给的不是根节点,但是我们可以通过给每个节点编号的方式来找到他对应的左右儿子,具体办法是用一个哈希表保存下标到节点值的映射,而每个节点的下标是按照层序一个满二叉树的方式来建立的,所以下标为k的左右儿子的下标为2k 和 2k+1。
class Solution {
public:
int pathSum(vector& nums) {
if(nums.empty())
return 0;
// 按照层序满二叉树建立下标
// 则一个下标为k的左右儿子 下标为2k 和 2k+1
unordered_map dict;
for(int i:nums){
int depth=i/100;
int p=i%100/10;
int val= i%10;
int temp=pow(2,depth-1)-1+p;
dict[temp]=val;
}
int res=0;
dfs(1,0,res,dict);
return res;
}
void dfs(int index,int cur,int& res,unordered_map &dict){
// 当前节点不存在
if(!dict.count(index))
return;
cur += dict[index];
if(!dict.count(2*index) && !dict.count(2*index+1)){
res += cur;
return;
}
dfs(2*index,cur,res,dict);
dfs(2*index+1,cur,res,dict);
}
};