In some cases, like the "hasPathSum" problem, where we are checking for a specific condition (e.g., targetSum == 0) at leaf nodes, we don't need manual backtracking. The recursion naturally backtracks as it reaches the leaf nodes, and the state is automatically maintained correctly.
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        if (root.left == null && root.right == null 
                              && targetSum == root.val) 
             return true;
        return hasPathSum(root.left, targetSum - root.val) 
                || hasPathSum(root.right, targetSum - root.val);
    }
}
Same problem,In such cases, we need to manually backtrack to the previous state when moving back up the recursive calls.
class Solution {
    int count = 0;
    public int pathSum(TreeNode root, int targetSum) {
        if (root == null) return 0;
        dfs(root, targetSum);
        return count;
    }
    public void dfs(TreeNode node, int targetSum) {
        if (node == null) return;
        targetSum -= node.val;
        if (targetSum == 0) {
            count++;
        }
        dfs(node.left, targetSum);
        dfs(node.right, targetSum);
        targetSum += node.val; // Backtrack, restore the previous state
    }
}
I don't understand how the values of parameters are passed in recursion, and why manual backtracking is needed when using the targetSum variable. Please help.