LeetCode 113. 路径总和 II(剑指 Offer 34. 二叉树中和为某一值的路径)

LeetCode 113. 路径总和 II
剑指 Offer 34. 二叉树中和为某一值的路径
 

给你二叉树的根节点 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

注意:本题与主站 113 题相同:力扣

 思路:

参考 LeetCode题解(关于不理解 slice 导致的 bug)

时间复杂度:O(N),N 为二叉树的节点数,先序遍历需要遍历所有节点。

空间复杂度:O(N) , 最差情况下,即树退化为链表时,path 存储所有树节点,使用 O(N)O(N) 额外空间。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

// 方式1 参考题解:https://leetcode.cn/problems/path-sum-ii/solutions/1075105/lc113-fengwei2002-guan-yu-bu-li-jie-slic-hank/
var res [][]int

func pathSum(root *TreeNode, targetSum int) [][]int {
    res = make([][]int, 0)
    subRes := make([]int, 0)
    dfs(root, targetSum, subRes)
    
    return res
}

func dfs(root *TreeNode, targetSum int, subRes []int) {
    if root == nil {
        return
    }

    targetSum -= root.Val
    subRes = append(subRes, root.Val)

    if root.Left == nil && root.Right == nil && targetSum == 0 {
        // cp := make([]int, len(subRes))
		// copy(cp, subRes)
		// res = append(res, cp)
        
        res = append(res, append([]int{}, subRes...))

        return
    }

    dfs(root.Left, targetSum, subRes)
    dfs(root.Right, targetSum, subRes)

    // 回溯,避免影响其他层的递归结果
    subRes = subRes[:len(subRes)-1]  // pop
    targetSum += root.Val
}

// func dfs(root *TreeNode, targetSum int, subRes []int) {
//     if root == nil {
//         return
//     }

//     subRes = append(subRes, root.Val)
//     if root.Left == nil && root.Right == nil && targetSum == root.Val {
//         // cp := make([]int, len(subRes))
// 		// copy(cp, subRes)
// 		// res = append(res, cp)

//         res = append(res, append([]int{}, subRes...))
//         return
//     }

//     dfs(root.Left, targetSum - root.Val, subRes)
//     dfs(root.Right, targetSum - root.Val, subRes)

//     // 回溯,避免影响其他层的递归结果
//     subRes = subRes[:len(subRes)-1]  // pop
//     targetSum += root.Val
// }

// 方式2 闭包写法:
func pathSum(root *TreeNode, target int) [][]int {
   	res := make([][]int, 0)
	nodes := make([]int, 0)
	var dfs func(node *TreeNode, t int)
	dfs = func(node *TreeNode, t int) {
		if node == nil {
			return
		}

        // @追加
		nodes = append(nodes, node.Val)  
        
        // (1)路径和=target (2)根节点 -> 叶子节点
		if t-node.Val == 0 && node.Left == nil && node.Right == nil {
            // 为避免修改原nodes数组,所以新创建一个临时数组 []int{}
			res = append(res, append([]int{}, nodes...))
		}

		dfs(node.Left, t-node.Val)
		dfs(node.Right, t-node.Val)
        
        // @回溯到添加元素前的状态,为了尝试另一种不同路线
        // 注意:整条链路dfs()下探完后,再回溯走其他路线
		nodes = nodes[:len(nodes)-1]     
	}

	dfs(root, target)
	return res
}

 路径总和 系列题目:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值