113. 路径总和 II

172 阅读1分钟

题目描述

image.png

方法一:DFS+回溯

如果某一路径dfs递归到叶子节点时,处理完是否记录该路径后,要在list中将该节点删掉,表示该节点已访问完毕。

class Solution {
    List<List<Integer>> res = new ArrayList<>();//记录路径
    List<Integer> path = new ArrayList<>();//存放结果

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        dfs(root, targetSum);
        return res;
    }

    public void dfs(TreeNode node, int targetSum) {
        if (node == null) {
            return;
        }
        path.add(node.val);//加入路径
        //满足条件:root为叶子节点,并且路径和=targetsum
        if (node.left == null && node.right == null && node.val == targetSum) {
            res.add(new ArrayList<>(path));
        }
        dfs(node.left, targetSum - node.val);
        dfs(node.right, targetSum - node.val);
        path.remove(path.size() - 1); //node左右节点均已访问,可以撤销
    }
}

方法二:bfs

  • 维护一个队列,用于按顺序存储node
  • 再维护一个队列,用于按顺序存储从root到该node的sum值
    • 当sum=target且node为叶子结点,网上找路径
    • 维护一个map,存<node,node.father>
class Solution {

    Map<TreeNode, TreeNode> map = new HashMap<>();//节点顺序map <node, node.father>
    
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>(); // 结果
        LinkedList<TreeNode> nodeQueue = new LinkedList<>(); // 存储node
        LinkedList<Integer> sumQueue = new LinkedList<>(); // 存储sum
        if (root == null) return res;
        nodeQueue.add(root);
        sumQueue.add(root.val);
        while (!nodeQueue.isEmpty()) {
            TreeNode node = nodeQueue.removeFirst();
            int curSum = sumQueue.removeFirst();
            if (node.left == null && node.right == null && curSum == targetSum) {
                res.add(getPath(node));//找到sum了,找路径并添加
            } else {
                if (node.left != null) {
                    nodeQueue.add(node.left);
                    sumQueue.add(curSum + node.left.val);//记录sum
                    map.put(node.left, node);//记录节点顺序
                }
                if (node.right != null) {
                    nodeQueue.add(node.right);
                    sumQueue.add(curSum + node.right.val);
                    map.put(node.right, node);
                }
            }
        }
        return res;
    }

    // 往上找路径
    public List<Integer> getPath(TreeNode node) {
        List<Integer> res = new ArrayList<>();
        while (node != null) {
            res.add(node.val);
            node = map.get(node);
        }
        Collections.reverse(res);// 反转
        return res;
    }
}

方法二:每次递归时,都复制上层的list来记录路径

这样效率太低

//16.57% 10.66%
public class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        dfs(root, sum, path, res);
        return res;
    }

    private void dfs(TreeNode root, int sum, List<Integer> path, List<List<Integer>> res) {
        if (root != null) {
            path.add(root.val);
            if (root.left == null && root.right == null && root.val == sum) {
                res.add(path);
            }
            dfs(root.left, sum-root.val, new ArrayList(path), res);//递归的下一层复制本层的路径
            dfs(root.right, sum-root.val, new ArrayList(path), res);//递归的下一层复制本层的路径
        }
    }
}