一【题目类别】
- 树
二【题目难度】
- 中等
三【题目编号】
- 113.路经总和II
四【题目描述】
- 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
- 叶子节点 是指没有子节点的节点。
五【题目示例】
- 示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]] - 示例 2:
输入:root = [1,2,3], targetSum = 5
输出:[] - 示例 3:
输入:root = [1,2], targetSum = 0
输出:[]
六【题目提示】
- 树中节点总数在范围 [0, 5000] 内
- -1000 <= Node.val <= 1000
- -1000 <= targetSum <= 1000
七【解题思路】
- 主要思路和【LeetCode每日一题】——112. 路径总和一样,只是需要一个List或者其他的保存路径,然后向左向右递归,最后回溯,注意Java每次都要new ArrayList(path)添加到res,否则每次都只是将path的地址add进去,并没有将真正的path加入到res中,导致每次path中的值改变,res里面的列表也随之改变
八【时间频度】
- 时间复杂度:时间复杂度包括 O ( N ) O(N) O(N)的树的递归和 O ( N ) O(N) O(N)的列表添加,所以总的时间复杂度为 O ( N 2 ) O(N^2) O(N2)
九【代码实现】
- Java语言版
package Tree;
import java.util.LinkedList;
import java.util.List;
public class p113_PathSumII {
p113_PathSumII left;
p113_PathSumII right;
int val;
p113_PathSumII() {
}
p113_PathSumII(int val) {
this.val = val;
}
public static void main(String[] args) {
// 初始化各个节点
p113_PathSumII root = new p113_PathSumII(5);
p113_PathSumII left1 = new p113_PathSumII(4);
p113_PathSumII left2 = new p113_PathSumII(11);
p113_PathSumII left3 = new p113_PathSumII(7);
p113_PathSumII left4 = new p113_PathSumII(2);
p113_PathSumII right1 = new p113_PathSumII(8);
p113_PathSumII right2 = new p113_PathSumII(13);
p113_PathSumII right3 = new p113_PathSumII(4);
p113_PathSumII right4 = new p113_PathSumII(5);
p113_PathSumII right5 = new p113_PathSumII(1);
// 初始化树
root.left = left1;
left1.left = left2;
left2.left = left3;
left2.right = left4;
root.right = right1;
right1.left = right2;
right1.right = right3;
right3.left = right4;
right3.right = right5;
p113_PathSumII p113_pathSumII = new p113_PathSumII();
int sum = 22;
// 传入参数
List<List<Integer>> res = p113_pathSumII.pathSum(root, sum);
// 打印结果
System.out.println("res = " + res);
}
// 用于存放结果,用于存放所有符合要求的路径
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> pathSum(p113_PathSumII root, int sum) {
// 如果当前结点为空,直接返回
if (root == null) {
return res;
}
// 临时List,用于存放当前符合要求的路径
LinkedList<Integer> temp = new LinkedList<>();
// 先把当前结点的值放进来
temp.add(root.val);
getPath(root, root.val, sum, temp);
return res;
}
public void getPath(p113_PathSumII root, int curSum, int sum, LinkedList<Integer> temp) {
// 如果当前结点是叶子节点,也就是递归遍历到了最后一个结点
if (root.left == null && root.right == null) {
// 如果是叶子节点,那么可以判断是否和sum相等
if (curSum == sum) {
// 如果相等,则将整条路经放入res中,这里每次都是new,因为要更新一下
res.add(new LinkedList<>(temp));
}
return;
}
// 判断左子树
if (root.left != null) {
// 如果左子树有值,那么将左子结点的值放入temp中,更新路径
temp.add(root.left.val);
// 开始向左递归,更新curSum的值,传入更新后的路径
getPath(root.left, curSum + root.left.val, sum, temp);
// 这步非常重要,使用回溯法,删除最后一个加入的结点,也就是当前结点,这样才能回到上一个结点重新遍历新的路径
temp.removeLast();
}
// 判断右子树,具体方法和判断左子树一样
if (root.right != null) {
temp.add(root.right.val);
getPath(root.right, curSum + root.right.val, sum, temp);
temp.removeLast();
}
}
}
- C语言版
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
/*结果数组索引,一定要写成全局变量,因为递归时这个索引不能回溯,要一直往前走*/
int resIndex;
void p113_PathSumII_getRes(struct TreeNode* root, int sum, int** res, int* path, int pathIndex, int* returnColumn)
{
/*递归跳出条件,到了叶子节点还没有满足条件的直接返回*/
if (root == NULL)
{
return;
}
/*每个路径都先加入*/
path[pathIndex++] = root->val;
/*某个结点的值等于此叶子结点的值,就找到了一条路径*/
if (sum - root->val == 0 && root->left == NULL && root->right == NULL)
{
/*注意这里要拷贝内存地址,不能直接把地址引用加入到res中*/
int* temp = (int*)malloc(sizeof(int)*pathIndex);
memcpy(temp, path, sizeof(int)*pathIndex);
res[resIndex] = temp;
returnColumn[resIndex] = pathIndex;
resIndex++;
}
/*向左子树递归*/
p113_PathSumII_getRes(root->left, sum - root->val, res, path, pathIndex, returnColumn);
/*向右子树递归*/
p113_PathSumII_getRes(root->right, sum - root->val, res, path, pathIndex, returnColumn);
/*回溯,向父结点的下一个结点继续递归*/
pathIndex--;
}
int** pathSum(struct TreeNode* root, int sum, int* returnSize, int** returnColumnSizes)
{
/*结果数组*/
int** res = (int**)malloc(sizeof(int*) * 2001);
/*结果数组索引初始化*/
resIndex = 0;
/*路经数组*/
int* path = (int*)malloc(sizeof(int) * 2001);
/*路经数组索引*/
int pathIndex = 0;
/*结果数组每一行索引*/
int* returnColumn = (int*)malloc(sizeof(int) * 2001);
/*开始递归*/
p113_PathSumII_getRes(root, sum, res, path, pathIndex, returnColumn);
/*结果数组每一行的长度*/
*returnColumnSizes = returnColumn;
/*结果数组的长度*/
*returnSize = resIndex;
/*返回结果*/
return res;
}
/*主函数省略*/
十【提交结果】
-
Java语言版
-
C语言版