【剑指offer刷题日记】34. 二叉树中和为某一值的路径

228 阅读2分钟

题目

输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

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

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

返回:

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

解法一 回溯DFS

这里首先有个重点,即需要结束点为叶节点,所以即使我们在途中发现和是已经够了,只要当前不是叶节点,也不算做一个合格解。这里其实我们可以用DFS,即一直向下找,直到找到叶节点为止。在一直向下的过程中,维护一个LinkedList cur 来装现在我们走的这条线所有经过的节点,因为我们只用一个 cur,所以我们需要用到回溯,如果不回溯的话,所有节点都会被加进去,这样就会得到错误的答案。

回溯的方法为先把当前走到的节点先加入cur,然后放入下一层循环,让下一层的循环的cur是带现在这个节点的,然后在调用完下一层循环后,再把当前节点移出cur,因为我们已经走过cur了,这样其他的路线就不会知道有这个节点的存在了。

再有注意的点为,因为我们一直在改动cur,所以当我们发现cur已经是一个合格的解后,放入result中时,我们需要复制一个cur的副本再把这个副本存入result。如果直接放cur,因为cur在后面会一直被操作,result里存的也会一直动。从而出现错误。

class Solution {
    // 要返回的最终所有解
    LinkedList<List<Integer>> result = new LinkedList<>();
    // 当前我们所拥有的解
    LinkedList<Integer> cur = new LinkedList<>();

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if(root == null) return result;
        DFS(root,sum);
        return result;
    }

    public void DFS(TreeNode node, int sum){
        if(node != null){
            // 只有节点的值为我们需要的,且当前节点为叶子节点,我们才算他为一个合格的解
            if(sum == node.val && node.left== null && node.right == null){
                    // 现在的node要放入解中
                    cur.add(node.val);
                    // 存在result里的必须为当前解的副本
                    result.add(new LinkedList(cur));
                    // 把现在的node从当前解移出
                    cur.removeLast();
                    return;
                
            }else{
                cur.add(node.val);
                // 循环向下看左孩子和右孩子的路
                DFS(node.left,sum-node.val);
                DFS(node.right,sum-node.val);
                cur.removeLast();
            }
        }
    }
}

时间复杂度:O(n) 所有的节点都被遍历了 空间复杂度:O(n) 有可能所有的节点都会被存入额外的空间cur里