力扣 112 路径总和【回溯】【递归函数要不要返回值】
全部刷题与学习记录
原题目
题目地址:112. 路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。
叶子节点 是指没有子节点的节点。
考查知识点
1、递归函数什么时候需要返回值
2、回溯的撤销操作在哪里进行
好的解法
【代码随想录】二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值? 中总结了递归函数在什么时候需要返回值!
答案:「如果需要搜索整颗二叉树,那么递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径了就要及时返回。」
本题就是搜索一条路径,并不是遍历整个二叉树,以回溯三步法进行分析:
1、函数参数及返回值:计数、当前节点
2、函数退出条件:遇到叶节点(又分成满足题目要求与不满足两种情况);
3、单层递归逻辑:向左右子节点递归,注意递归之前要判断左右子节点是否为空节点;回溯的撤销操作(将回溯中修改的变量全部复原)
值得说的是,很久没做回溯题,回溯撤销的位置一定要记住:回溯之后马上进行撤销,也就是在单层逻辑中进行撤销,不要在结束条件中进行撤销
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 {
private:
bool backTrack(TreeNode* curNode, int target) {
if (!curNode->left && !curNode->right && target == 0) return true;
if (!curNode->left && !curNode->right) return false;
if (curNode->left) {
target -= curNode->left->val;
if (backTrack(curNode->left, target)) return true;
target += curNode->left->val;
}
if (curNode->right) {
target -= curNode->right->val;
if (backTrack(curNode->right, target)) return true;
target += curNode->right->val;
}
return false;//这句退出很关键,经常会忘记,给函数加一个保险,防止返回true的条件全都不满足
}
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == nullptr) return false;
bool res = backTrack(root, targetSum - root->val);
return res;
}
};