给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
思路
递归法
1. 递归参数和返回值
传入的参数为根节点和int型路径和计数器
返回值为bool类型,确定是否找到合适的路径
2. 终止条件
不需要从0加节点的值判断到达叶子节点后的和是否为22。
只需要将count设为目标值,递减后判断到达叶子节点是否为0即可。
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回
3. 单层递归逻辑
终止条件是判断叶子节点,就不需要让空节点进入递归过程。
递归函数有返回值,如果返回TRUE,则立即返回即可。
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val;
if (traversal(cur->right, count)) return true;
count += cur->right->val;
}
return false;
也可以简写为下面的形式,count值在返回后不会变化,包含了回溯的过程。
if (cur->left) { // 左 (空节点不遍历)
// 遇到叶子节点返回true,则直接返回true
if (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑
}
if (cur->right) { // 右 (空节点不遍历)
// 遇到叶子节点返回true,则直接返回true
if (traversal(cur->right, count - cur->right->val)) return true; // 注意这里有回溯的逻辑
}
return false;
递归法完整代码:
class Solution {
public:
bool traversal(TreeNode* cur, int count){
if(!cur->left && !cur->right && count == 0) return true;
if(!cur->left && !cur->right) return false;
if(cur->left){
if(traversal(cur->left, count - cur->left->val))
return true;
}
if(cur->right){
if(traversal(cur->right, count - cur->right->val))
return true;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == NULL) return false;
return traversal(root, targetSum - root->val);
}
};
更加简洁的代码:
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if (!root) return false;
if (!root->left && !root->right && sum == root->val) {
return true;
}
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
}
};