前言
又是学习LeetCode二叉树部分内容的新一天,希望博主记录的内容能够对大家有所帮助 ,一起加油吧朋友们!💪💪💪
路径总和
LeetCode题目链接
题目的意思是在以root为根节点的二叉树中是否存在根节点到叶子节点的路径使得路径节点值相加等于目标和targetSum🤔🤔🤔

思路:递归处理的话,很明显该题需要回溯处理,因为递归到叶子节点时如果计算得到路径节点值相加(需要一个变量来记录)不等于给定的targetSum,则回溯往下一个路径处理,梳理完毕,我们接下来进行递归三要素的确定。🤔🤔🤔
递归三要素:
1 2 3 4
|
boolean hasPathSum(TreeNode root, int targetSum){}
|
1 2 3 4 5 6 7
|
if(root == null)return false; targetSum -= root.val; if(root.left == null && root.right == null){ return targetSum == 0; }
|
1 2 3 4 5 6 7 8 9
| if(root.left){ if(hasPathSum(root.left, targetSum))return true; }
if(root.right){ if(hasPathSum(root.right, targetSum))return true; } return false;
|
接着我们来梳理迭代方法的处理逻辑吧,除了层序遍历用栈存储节点外还需要一个栈来记录对应节点到根节点的节点值的和🤔🤔🤔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution{ public boolean hasPathSum(TreeNode root, int targetSum){ if(root == null)return false; Stack<TreeNode> stackNode = new Stack<>(); Stack<Integer> stackSum = new Stack<>(); stackNode.push(root); stackSum.push(root.val); while(!stackNode.isEmpty()){ int size = stackNode.size(); for(int i = 0; i < size; i++){ TreeNode cur = stackNode.pop(); int sum = stackSum.pop();
if(cur.left == null && cur.right == null && sum == targetSum)return true; if(cur.right != null){ stackNode.push(cur.right); stackSum.push(sum + cur.right.val); } if(cur.left != null){ stackNode.push(cur.left); stackSum.push(sum + cur.left.val); } } } return false; } }
|
路径总和ii
LeetCode题目链接
这次是给二叉树的根节点root和一个targetSum,要求找出所有从根节点到叶子节点路径总和等于targetSum的路径。🤔🤔🤔

思路:首先就是递归到叶子节点(左右节点为null的节点),因为要返回路径,所以递归函数不需要返回值,而且要找出所有的路径即要遍历整个二叉树,梳理完毕,我们接下来进行递归三要素的确定。🤔🤔🤔
递归三要素:
1 2 3 4 5
|
private List<List<Integer>> result = new ArrayList<>(); private void findPaths(TreeNode root, int targetSum, List<Integer> path){}
|
- 确定递归出口(这里因为path是传入的参数,所以在添加path的时候需要创建副本进行添加,否则回溯时会影响path)🤔🤔🤔
1 2 3 4 5 6 7 8
| path.add(root.val); if(root.left == null && root.right == null){ if(targetSum - root.val == 0){ result.add(new ArrayList<>(path)); } return; }
|
在 Java 中,new ArrayList<>(path) 是构造函数的一个调用,它的作用是创建一个新的ArrayList实例,并且用给定的集合(在这里是path)来初始化它。这意味着这个新创建的列表会包含path中的所有元素,但它是一个独立的对象,和原来的path没有任何关系。 🤔🤔🤔
1 2 3
| List<Integer> path = new ArrayList<>(Arrays.asList(5, 4, 11)); List<Integer> temp = new ArrayList<>(path);
|
1 2 3 4 5 6 7 8 9
| if(root.left != null){ findPaths(root.left, targetSum - root.val, path); path.remove(path.size() - 1); } if(root.right != null){ findPaths(root.right, targetSum - root.val, path); path.remove(path.size() - 1); }
|
迭代法的话假如说用层序遍历,需要有记录节点、节点的路径以及剩余目标值的栈,会比较复杂,所以这里我们就不过多进行迭代法的学习了🤔🤔🤔
路径总和iii
LeetCode题目链接
给定一个二叉树的根节点root和一个整数targetSum,求二叉树里节点值和等于targetSum的路径的数目。这里的路径不需要从根节点开始但是必须是向下的路径。🤔🤔🤔

思路:需要记录一个节点的根节点到其的所有路径和的出现次数,可以使用哈希表,其中在节点遍历时我们更新一个currentSum(树根节点到当前节点的路径和)🤔🤔🤔,在访问当前节点的时把currentSum插入到哈希表中,当更新currentSum的时候需要检查有没有之前保存的路径和可以与当前的currentSum合并等于targetSum,有的话则说明找到了一条路径等于目标值。回溯的时候需要撤回之前的路径和记录🤔🤔🤔

递归三要素:
1 2 3 4
| private int result = 0; private HashMap<Integer, Integer> prefixSumMap = new HashMap<>(); private void dfs(TreeNode root, int currentSum, int targetSum){}
|
1 2
| if(root == null)return;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| currentSum += root.val;
if(prefixSumMap.containsKey(currentSum - targetSum)){ result += prefixSumMap.get(currentSum - targetSum); }
prefixSumMap.put(currentSum, prefixSumMap.getOrDefault(currentSum, 0) + 1);
dfs(root.left, currentSum, targetSum); dfs(root.right, currentSum, targetSum);
prefixSumMap.put(currenSum, prefixSumMap.get(currentSum) - 1);
|
逻辑处理梳理,这里其实最核心的处理逻辑就是一个哈希表检查的逻辑🤔🤔🤔

以及一个目标路径次数更新的逻辑🤔🤔🤔


递归完整代码如下:
迭代的话需要用栈来存储节点和当前的路径和,也比较复杂,这里博主就也先不码了,留到二轮复习是时候再啃一下🫡🫡🫡
总结
今天就到这里啦,明天继续加油👊👊👊