题目说明:
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
思路
- 遍历这棵树,使用临时集path并记录路径。
- 递归过程: 将当前结点加入临时集合, 并用sum减掉当前结点的值 ,继续遍历其左右子树 。
- 递归终止条件: 抵达叶子节点。 此时判断是否满足条件。如果是,就加入结果集。
深度优先遍历(dfs)
dfs 就是一路走到头,碰到叶子节点才会返回。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum)
{
List<List<Integer>> list = new ArrayList<> ();
List<Integer> path = new ArrayList<Integer>() ;
if(root==null)
return list;
dfs(root , sum , path , list) ;
return list ;
}
private void dfs(TreeNode root ,int sum , List<Integer> path ,List<List<Integer>> list )
{
if(root ==null)
return ;
// 递归过程: 将当前值加入临时值
path.add(root.val) ;
sum -=root.val ;
//递归结束条件: 遍历到叶子节点
if(root.left ==null && root.right == null)
{//如果已经是叶子节点了
if(sum==0)
{
list.add(new ArrayList<> (path)) ;
}
return ;
}
dfs(root.left , sum ,new ArrayList<Integer>(path) , list) ;
dfs(root.right, sum , new ArrayList<Integer> (path) ,list) ;
}
}
//其实就是树的遍历
回溯
回溯的特点, 就是在遍历到叶子节点后,会返回上一级 。此时应该将叶结点从临时集中移除

class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum)
{
List<List<Integer>> list = new ArrayList<> ();
List<Integer> path = new ArrayList<Integer>() ;
if(root==null) return list;
back(root , sum , path , list) ;
return list ;
}
private void back(TreeNode root ,int sum , List<Integer> path ,List<List<Integer>> list )
{
if(root ==null)
return ;
path.add(root.val) ;
if(root.left ==null && root.right == null && sum == root.val )
{//如果已经是叶子节点了
list.add(new ArrayList<> (path)) ;
}
back(root.left , sum-root.val ,path , list) ;
back(root.right, sum-root.val , path ,list) ;
path.remove( path.size() -1 ) ; // 回溯法的体现。
}
}
总结
两者的代码比较相似, 由于回溯算法不需要每次都创建新的临时集合,效率较高
大家可以思考为什么要dfs中每一次都要创建新的集合, 而回溯算法只需要在添加时才需要? 临时集合path中的元素究竟发生了什么变化?
博主也是萌新, 不能很好的解释这个问题, 如果你看到这里,并且有思路的,欢迎分享和交流。
关于程序顺序的设计
有时候一个程序的代码顺序会使得整个程序运行结果完全不同, 因此,逻辑思维非常的重要 ,先做那一步,再做那一步,在设计时要思考清楚。
博主本人在做这道题时, 就因为把递归过程放在递归终止条件之后,导致最后的叶结点没有加入到临时集合,折腾了很久。 参看了评论区中的答案后,才明白过来。
学习递归和二叉树,刚开始是十分费劲的,这点博主深有体会,但是,做对一道题的喜悦也是无语伦比的, 博客有几个月没有更新了,虽然没有什么人看, 但接下一直在写,无论是对是错,暴露问题才是解决问题的前提。 接下来会将自己在3,4,5月做二叉树和递归相关的总结和题目集合起来更新。希望有所得。
本文探讨了在给定二叉树和目标和的情况下,寻找所有从根节点到叶子节点路径总和等于目标和的路径问题。通过深度优先搜索(DFS)和回溯两种方法进行解析,对比了它们的效率差异。

1万+

被折叠的 条评论
为什么被折叠?



