【LeetCode每日一题】——113.路经总和II

一【题目类别】

二【题目难度】

  • 中等

三【题目编号】

  • 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)

九【代码实现】

  1. 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();
        }
    }

}
  1. 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;
}

/*主函数省略*/

十【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. C语言版
    在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值