【LeetCode】113. 路径总和 II(同剑指 Offer 34)

这篇博客介绍了如何解决LeetCode 113问题和剑指 Offer 34挑战,即寻找二叉树中根到叶子节点路径和等于给定值的所有路径。文中提供了两种解决方案:深度优先搜索(DFS)和广度优先搜索(BFS),并分别分析了它们的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

一、题目

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

给定如下二叉树,以及目标和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]

二、解决

1、DFS(回溯–先序遍历+路径记录)

思路:

  • 先序遍历:根 - 左 - 右
  • 路径记录:记录从根节点到当前节点的路径。当满足:(1)根节点到叶节点形成路径。(2)各节点值的和等于目标值sum,可将该路径加入结果列表。
    1
    这里附下DFS代码模板:
public List<Integer> dfs(Node root, int curLayer, List<Integer> result) {
	// 终止条件
    if (root == null || curlayer > n) return result;  // 数据非法
    if (curLayer.val == true) { // 满足条件
	    result.add(xxx);  // xxx: node.val / curlayer / path
    	return result;
    }
    if (canCutBranch()) return result;
	
	visited[root] = true;  // 标记:处理当前顶点,记录为已访问
    for (Node next : root) { // 遍历与当前顶点相邻的所有未访问顶点
        visited[next] = true; 
        result.add(xxx) // 标记更改: 修改result/path/其他
        dfs(next, curLayer + 1, result)
        visited[next] = false; 
        result.remove(xxx) // 恢复更改: 还原result/path/其他
	}
	return result;
}

代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
 
class Solution {
    LinkedList<List<Integer>> res = new LinkedList<>();
    LinkedList<Integer> path = new LinkedList<>(); 
    
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        recur(root, sum);
        return res;
    }
    private void recur(TreeNode root, int sum) {
    	// Terminator
        if(root == null) return;
        path.add(root.val);
        sum -= root.val;
        if(sum == 0 && root.left == null && root.right == null) {
            res.add(new LinkedList(path));
//            return;  
// 多一个return,就会提前跳出,导致path少删去一个节点,最终使得path比sum多一个节点,不再一一对应。
// 例子:
// 输入:
// [5,4,8,11,null,13,4,7,2,null,null,5,1]
// 22
// 输出:
// [[5,4,11,2],[5,4,8,4,5]]
        recur(root.left, sum);
        recur(root.right, sum);
        path.removeLast();
    }
}

时间复杂度: O ( n 2 ) O(n^2) O(n2)。最坏情况下,此时上半部分退化为链表,下半部变成完全二叉树,且每一条路径都满足要求。
空间复杂度: O ( n ) O(n) O(n)

2、BFS

思路:

DFS是先从上往下遍历,BFS是一行一行遍历。
2

再附下BFS代码模板:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

public List<List<Integer>> BFS(TreeNode root) {

	List<List<Integer>> allResults = new ArrayList<>();
    if (root == null)  return allResults;
    
    Queue<TreeNode> nodes = new LinkedList<>();
    nodes.add(root);
    while (!nodes.isEmpty()) {
        int levelSize = nodes.size();
        List<Integer> results = new ArrayList<>();
        for (int i = 0; i < levelSize; i++) {
            TreeNode currNode = nodes.poll();
            results.add(currNode.val);
            if (currNode.left != null)  nodes.add(currNode.left);
            if (currNode.right != null)  nodes.add(currNode.right);
        }
        allResults.add(results);
    }
    return allResults;
}

代码:


class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> res = new ArrayList<>();
        //如果节点为空直接返回
        if (root == null)
            return res;
        //使用两个队列,一个存储结点,一个存储从更结点到当前节点的路径
        Queue<TreeNode> queueNode = new LinkedList<>();
        Queue<List<Integer>> queueList = new LinkedList<>();
        //根节点入队
        queueNode.add(root);
        //根节点的路径入队
        List<Integer> list = new ArrayList<>();
        list.add(root.val);
        queueList.add(list);

        while (!queueNode.isEmpty()) {
            //当前节点出队
            TreeNode node = queueNode.poll();
            //当前节点的路径出队
            List<Integer> tempList = queueList.poll();
            if (node.left == null && node.right == null && node.val == sum) {
                //如果满足条件,就把路径存储到res中
                res.add(tempList);
            }
            //左子节点不为空,左子节点和路径入队
            if (node.left != null) {
                tempList.add(node.left.val);
                queueList.add(new ArrayList<>(tempList));
                node.left.val += node.val;
                queueNode.add(node.left);
                tempList.remove(tempList.size() - 1);
            }
            //右子节点不为空,右子节点和路径入队
            if (node.right != null) {
                tempList.add(node.right.val);
                queueList.add(new ArrayList<>(tempList));
                node.right.val += node.val;
                queueNode.add(node.right);
            }
        }
        return res;
    }
}

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

三、参考

1、面试题34. 二叉树中和为某一值的路径(回溯法,清晰图解)
2、路径总和 II
3、DFS,BFS共5种方式解决,2种击败了100%的用户
4、Simple DFS Java Solution
5、Java Solution: iterative and recursive
6、Another accepted Java solution

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值