首先给递归是否需要返回值的结论:
- 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii的情况)
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236.二叉树的最近公共祖先的情况)
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(112.路径总和的情况)
112.路径总和
题目描述:
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点
解答:
采用递归加回溯的办法解决。遍历采用先序遍历(中左右)
依旧先考虑递归三要素:
(1)参数和返回值:根节点肯定需要,其次需要一个参数用于保存路径之和,一个参数保存要找的目标和(targetSum)。
此处只需要找出一条满足条件的路径,遇到了符合条件的路径直接返回即可,所以需要返回值。采用bool类型的返回值。
bool PathSum(TreeNode* root, int sum, int targetSum){}
(2)终止条件:遇到叶子节点判断路径和是否满足条件,若满足返回true,否则false
if (root->left == NULL && root->right == NULL){
if (sum == targetSum)
return true;
else
return false;
}
(3)内部处理逻辑:因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。
其中隐含了回溯,再调用函数返回后sum并未发生改变,等同于回溯,但是没有显式表达出来。
代码实现:
class Solution {
public:
bool PathSum(TreeNode* root, int sum, int targetSum){
sum += root->val;
bool left, right;
if (root->left == NULL && root->right == NULL){
if (sum == targetSum)
return true;
else
return false;
}
if (root->left){
left = PathSum(root->left, sum, targetSum);
}
if (root->right){
right = PathSum(root->right, sum, targetSum);
}
if (left || right) return true;
else return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
return PathSum(root, 0, targetSum);
}
};
精简版代码:
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
if (!root->left && !root->right && targetSum == root->val) {
return true;
}
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
113. 路径总和 II
题目描述:
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
解答:
依然采用递归法实现,回溯的思路和上一题基本相同,唯一的不同在于此处无须返回值。此处需要遍历完整棵树且不用处理递归返回值,正是开头所提到的第一种情况。
满足条件的路径存储在结果集合中,无需作为返回值返回。
依然考虑递归三要素:
(1)参数和返回值:根节点肯定需要,然后需要一个参数保存当前的路径,其次需要一个参数用于保存满足条件的路径,一个参数保存路径和,一个参数保存要找的目标和(targetSum)。无需返回值。
(2)终止条件:遇到叶子节点比较和targetSum是否相同,相同则存入result中,不同则返回。
(3)内部处理逻辑:与上一题类似,递归调用即可。
代码实现:
class Solution {
public:
void PathSum(TreeNode* root, vector<int>path, vector<vector<int>>&result, int sum, int targetSum){
sum += root->val;
path.push_back(root->val);
if (root->left == NULL && root->right == NULL){
if (sum == targetSum)
result.push_back(path);
else
return ;
}
if (root->left){
PathSum(root->left, path, result, sum, targetSum);
}
if (root->right){
PathSum(root->right, path, result, sum, targetSum);
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>>result;
vector<int>path;
if (root)
PathSum(root, path, result, 0, targetSum);
return result;
}
};