《中英双解》leetCode Path Sum II(路径总和2)

Given the root of a binary tree and an integer targetSum, return all root-to-leaf paths where the sum of the node values in the path equals targetSum. Each path should be returned as a list of the node values, not node references.

A root-to-leaf path is a path starting from the root and ending at any leaf node. A leaf is a node with no children. 

Example 1:


Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: [[5,4,11,2],[5,8,4,5]]
Explanation: There are two paths whose sum equals targetSum:
5 + 4 + 11 + 2 = 22
5 + 8 + 4 + 5 = 22
Example 2:


Input: root = [1,2,3], targetSum = 5
Output: []
Example 3:

 

Input: root = [1,2], targetSum = 0
Output: []
 

Constraints:

The number of nodes in the tree is in the range [0, 5000].
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

这题我们提供多个思路尝试解答,看看各自的执行效率。

第一个我们用后续遍历的写法。

拿到这个题相信大家都会想到,我们需要计算总和,或者相减最后的那个数等于root.val,这个时候我们可以直接找到最后的叶子结点同时这个叶子结点的值还等于targetSum。这里是一个结果,同时还要完成的是递归找到所有左子树的结点和右子树的结点,利用后续遍历进行求解。

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
      //第一步我们也是需要判断是否为空
      if(root == null){
         return new ArrayList<>();
      }
      //创建一个List用来存储结果
      List<List<Integer>> res = new ArrayList<>();
      //现在我们面临的问题是找到多个可达路径,所以需要先找到末尾结点,并判断尾结点是否等于targetSum
      //这条语句执行之后得到的结果肯定就是输出结果
      if(root.left != null && root.right != null && targetSum == root.val){
         //如果相等
         List<Integer> list = new ArrayList<>();
         list.add(root.val);
         res.add(list);
         return res;
      }
      //上面这几条语句如果不递归的花最后可能只会是一个数而不是一组数
      List<Integer> left = pathSum(root.left,targetSum - root.val);
      List<Integer> right = pathSum(root.right,targetSum - root.val);
      //这个时候所有的有效数据都存储在这两个结点里面了
      
      //后续遍历输出
      for(List<Integer> l1 : left){
         l1.add(0,root.val);
         res.add(l1);   
      }
      for(List<Integer> l2 : right){
         l2.add(0,root.val);
         res.add(l2);   
      }
      return res;
   }
}

 然后我们再看看如何用BFS进行解题

class Solution {
   
   //使用广度优先的话我们需要两个方法,所以此时在外面定义全局变量
   List<List<Integer>> res = new ArrayList<>();
   //为了节省空间,使用Map存储父节点
   Map<TreeNode,TreeNode> map = new HashMap<>();

   public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
      //使用两个队列进行存储节点和节点的值
      Queue<TreeNode> queue1 = new LinkedList<>();
      Queue<Integer> queue2 = new LinkedList<>();
      queue1.add(root);
      queue2.add(0);
  
      //当队列不为空
      while(!queue1.isEmpty()){
         TreeNode node = queue1.poll();
         int number = queue2.poll() + node.val;//注意需要家node.val这是为了计算总值
         if(node.left == null && node.right == null){
            if(number == targetNum){
               getPath(node);
            }
         } else {
            if(node.left != null){
               //map存储父节点
               map.put(node.left,node);
               queue1.add(node.left);
               queue2.add(num);
            }
            if(node.right != null){
               //map存储父节点
               map.put(node.right ,node);
               queue1.add(node.right );
               queue2.add(num);
            }

         }
      }
         return ret;
      
   }
    public void getPath(TreeNode node) {
        List<Integer> temp = new LinkedList<Integer>();
        while (node != null) {
            temp.add(node.val);
            node = map.get(node);
        }
        Collections.reverse(temp);//注意需要反转链表
        ret.add(new LinkedList<Integer>(temp));
    }
}

再看看深度优先

class Solution {
    List<List<Integer>> ret = new LinkedList<List<Integer>>();
    Deque<Integer> path = new LinkedList<Integer>();

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

    public void dfs(TreeNode root, int targetSum) {
        if (root == null) {
            return;
        }
        path.offerLast(root.val);
        targetSum -= root.val;
        if (root.left == null && root.right == null && targetSum == 0) {
            ret.add(new LinkedList<Integer>(path));
        }
        dfs(root.left, targetSum);
        dfs(root.right, targetSum);
        path.pollLast();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值