#LeetCode每日一题【二叉树专题】
- 路径总和 II
https://leetcode-cn.com/problems/path-sum-ii/ - 分析
寻找一颗二叉树中 所有 从根节点到叶子节点 路径总和等于给定目标和的路径
考虑深度优先搜索,每当到达一个叶子节点的时候,判断当前值是不是满足目标和,满足即将其加入到最终结果集;
需要注意的是,当某一个根节点及其下面都遍历完了之后,在继续往上,需要注意回溯,不然会影响下一次递归结果集 - 实现
List<List<Integer>> ans = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
LinkedList<Integer> res = new LinkedList<>();
pathSum(root, targetSum, res);
return ans;
}
// 深度优先搜索+回溯
private void pathSum(TreeNode root, int targetSum, LinkedList<Integer> res) {
if (root == null) return;
res.add(root.val);
if (root.left == null && root.right == null) {
// 叶子节点满足最终条件
if (root.val == targetSum) {
// 要new一个集合进去,不然后面会被同步修改
ans.add(new LinkedList<>(res));
}
}
pathSum(root.left, targetSum - root.val, res);
pathSum(root.right, targetSum - root.val, res);
// 要回溯,把当前的节点从集合中去除
res.pollLast();
}
LeetCode耗时:1ms
- 方案二
如果不使用回溯的情况下,要确保每次递归之间list传递互不影响,还可以在每次递归之前生成一个新集合,但是会存在很多额外的时间以及空间开销
List<List<Integer>> ans = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
LinkedList<Integer> res = new LinkedList<>();
pathSum2(root, targetSum, res);
return ans;
}
// 深度优先搜索+每次递归都生成一个新集合,保证不会干扰其他递归分支
private void pathSum2(TreeNode root, int targetSum, LinkedList<Integer> res) {
if (root == null) return;
// 每次递归进来都重新new一个集合,这样能保证参数res不会在每次递归中相互干扰,也就不用回溯
LinkedList<Integer> temp = new LinkedList<>(res);
temp.add(root.val);
if (root.left == null && root.right == null) {
if (root.val == targetSum) {
ans.add(temp);
}
}
pathSum2(root.left, targetSum - root.val, temp);
pathSum2(root.right, targetSum - root.val, temp);
}
LeetCode耗时:5ms
可以看出时间和空间上都增加很多
- 总结
- 关于递归和回溯,这里面有些介绍可以加深下理解
链接 - 分支污染问题有两种解决思路:
第一种:回溯
第二种:每次递归都创建一个全新的对象