1. 问题描述:
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-ii
2. 思路分析:
① 题目不难理解,对于这种寻找所有路径使用dfs搜索的方法来解决就再适合不过了,因为dfs在搜索的时候回搜索所有的路径,所以我们在搜索的时候计算从根节点到叶子节点的路径的总和是多少即可
② 因为求解的是二叉树的根节点到叶子节点的路径,所以我们不妨在纸上画出具体的测试例子,分析一下具体的代码需要怎么样写,比如对于根节点5我们可以存在着两种的选择,所以我们可以分别递归左子树与右子树,所以对于每一个节点都是这样递归下去,直到到达了叶子节点,递归左右子树其实比较简单,直接两个递归的方法即可,关键是怎么样记录其中的路径,我们可以使用List来记录中间的路径,得到递归到叶子节点的时候表示一条路径已经形成这个时候判断路径的值是否等于目标值即可,当递归左子树的时候将左子树的值加入到list中,表示选择左子树进行递归,并且在左子树递归完成之后需要进行回溯也就是需要将递归之前加入的元素删除掉,比如递归路径5--4--11--7到达了叶子节点那么return之后返回到上一层递归的地方,此时的List中存放了之前递归加入的叶子节点7所以当左子树递归完成之后需要将上一次加入的节点删除掉,也就是删除掉最后一个元素,所以我们删掉7之后继续右子树的递归,递归返回的当前节点为11,所以删除7之后继续右子树的递归也就是尝试其他的路径
② 对于左右子树我们在递归结束之后都需要将最后加入的元素删除掉(回溯)这样我们在尝试其他路径的时候才不会受到影响,所以层层返回的时候也会将之前到达当前节点路径都删除掉,这个结合具体的测试用例还是比较好理解的,当到达了叶子节点表示一条路径已经生成,list记录的就是我们的路径上的数字,判断是否等于目标值,若想等加入结果集中,等到所有递归完成结果集中就是需要求解的答案了,其实中间的逻辑还是比较好理解的,关键在于list记录路径的时候需要回溯
3. 代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int sum) {
if(root == null) return res;
List<Integer> list = new ArrayList<>();
list.add(root.val);
dfs(root, sum, root.val, list);
return res;
}
private void dfs(TreeNode root, int sum, int k, List<Integer> cur) {
if (root == null) return;
/*叶子节点*/
if (root.left == null && root.right == null){
if (k == sum){
List<Integer> newlist = new ArrayList<>();
for (int i = 0; i < cur.size(); ++i){
newlist.add(cur.get(i));
}
res.add(newlist);
}
return;
}
/*使用下面的方法来解决*/
if (root.left != null){
cur.add(root.left.val);
dfs(root.left, sum, k + root.left.val, cur);
cur.remove(cur.size() - 1);
}
if (root.right != null){
cur.add(root.right.val);
dfs(root.right, sum, k + root.right.val, cur);
cur.remove(cur.size() - 1);
}
}
}
增加测试的代码:可以使用idea的debug调试找出错误
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Solution {
public static class TreeNode{
private TreeNode left;
private TreeNode right;
private int val;
public TreeNode(int val) {
this.val = val;
}
}
private static TreeNode createBinaryTree(int[] arr) {
TreeNode nodeArr[] = new TreeNode[arr.length];
/*初始化*/
for (int i = 0; i < arr.length; ++i){
nodeArr[i] = new TreeNode(arr[i]);
}
for (int i = 0; i < arr.length; ++i){
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < arr.length) nodeArr[i].left = nodeArr[l];
else nodeArr[i].left = null;
if (r < arr.length) nodeArr[i].right = nodeArr[r];
else nodeArr[i].right = null;
}
return nodeArr[0];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
/*int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; ++i){
arr[i] = sc.nextInt();
}*/
int sum = sc.nextInt();
//TreeNode root = createBinaryTree(arr);
TreeNode root = create();
//preOrder(root);
System.out.println(pathSum(root, sum));
}
/*前序遍历检查是否正确*/
private static void preOrder(TreeNode node) {
if (node == null) return;
System.out.println(node.val);
preOrder(node.left);
preOrder(node.right);
}
//测试用例二叉树
private static TreeNode create() {
TreeNode root = new TreeNode(5);
TreeNode l = new TreeNode(4);
TreeNode r = new TreeNode(8);
root.left = l;
root.right = r;
TreeNode ll = new TreeNode(11);
l.left = ll;
l.right = null;
TreeNode rl = new TreeNode(13);
TreeNode rr = new TreeNode(4);
r.left = rl;
r.right = rr;
TreeNode lll = new TreeNode(7);
TreeNode llr = new TreeNode(2);
ll.left = lll;
ll.right = llr;
TreeNode rrl = new TreeNode(5);
TreeNode rrr = new TreeNode(1);
rr.left = rrl;
rr.right = rrr;
lll.left = null;
lll.right = null;
llr.left = null;
llr.right = null;
rrl.left = null;
rrr.right = null;
return root;
}
static List<List<Integer>> res = new ArrayList<>();
public static List<List<Integer>> pathSum(TreeNode root, int sum) {
if(root == null) return res;
List<Integer> list = new ArrayList<>();
list.add(root.val);
dfs(root, sum, root.val, list);
return res;
}
private static void dfs(TreeNode root, int sum, int k, List<Integer> cur) {
if (root == null) return;
/*叶子节点*/
if (root.left == null && root.right == null){
if (k == sum){
List<Integer> newlist = new ArrayList<>();
for (int i = 0; i < cur.size(); ++i){
newlist.add(cur.get(i));
}
res.add(newlist);
}
return;
}
/*使用下面的方法来解决*/
if (root.left != null){
cur.add(root.left.val);
dfs(root.left, sum, k + root.left.val, cur);
cur.remove(cur.size() - 1);
}
if (root.right != null){
cur.add(root.right.val);
dfs(root.right, sum, k + root.right.val, cur);
cur.remove(cur.size() - 1);
}
}
}