路径总和-leetcode刷题记录三

292 阅读2分钟

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

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

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

给定以下输入
[5,4,8,11,null,13,4,7,2,null,null,null,1]
22

题目链接

如何构建二叉树以及利用DFS求解

package KNumber;/*
 * Created by lizeyu on 2020/8/8 11:09
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

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

        TreeNode(int x) {
            val = x;
        }
    }
//广度优先算法
    public boolean hasPathSum(TreeNode root, int sum) {
        //如果根节点是空,即整棵树是空的
        if (root == null) {
            return false;
        }
        //分别存储节点以及路径和的队列
        Queue<TreeNode> treeNodeQueue = new LinkedList<TreeNode>();
        Queue<Integer> integerQueue = new LinkedList<Integer>();
        //入队列
        treeNodeQueue.offer(root);
        integerQueue.offer(root.val);
        //遍历树的所有节点,直到找到路径和为sum的叶子节点
        while (!treeNodeQueue.isEmpty()) {
            //分别得到队首的元素
            TreeNode tempNode = treeNodeQueue.poll();
            Integer tempSum = integerQueue.poll();
            //找到了叶子节点以及路径和等于sum
            if (tempNode.left == null && tempNode.right == null && tempSum == sum) {
                return true;
            }
            //分别把中间节点的左右节点(如果存在)加入到队列当中
            if (tempNode.left != null) {
                treeNodeQueue.offer(tempNode.left);
                integerQueue.offer(tempSum + tempNode.left.val);
            }
            if (tempNode.right != null) {
                treeNodeQueue.offer(tempNode.right);
                integerQueue.offer(tempSum + tempNode.right.val);
            }
        }
        return false;
    }

    public static TreeNode stringToTreeNode(String input) {
        input = input.trim().substring(1, input.length() - 1);
        if (input.length() == 0) {
            return null;
        }
        String[] strings = input.split(",");
        String item = strings[0];
        TreeNode root = new TreeNode(Integer.parseInt(item));
        Queue<TreeNode> nodeQueue = new LinkedList<>();
        nodeQueue.add(root);
        int index = 1;
        while (!nodeQueue.isEmpty()) {
            TreeNode node = nodeQueue.remove();
            if (index == strings.length) {
                break;
            }
            item = strings[index++].trim();
            if (!item.equals("null")) {
                int leftNum = Integer.parseInt(item);
                node.left = new TreeNode(leftNum);
                nodeQueue.add(node.left);
            }
            if (index == strings.length) {
                break;
            }

            item = strings[index++].trim();
            if (!item.equals("null")) {
                int rightNum = Integer.parseInt(item);
                node.right = new TreeNode(rightNum);
                nodeQueue.add(node.right);
            }
        }
        return root;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = in.readLine()) != null) {
            TreeNode root = stringToTreeNode(line);
            line = in.readLine();
            int sum = Integer.parseInt(line);
            System.out.println(new Knumber().hasPathSum(root, sum));
        }
    }
}

递归求解

  • 寻找一条以root为根的、总和等于sum的路径可以分解为寻找一条以root.left为根或者以root.right为根的、总和等于sum - root.val的路径。
  • 随着递归,每经过一个路径上一个非叶子节点,要寻找的值就减去了当前节点的值;
  • 当到达叶子节点时,已经构成一条完整路径,此时若要寻找的值恰好和叶子节点的值相同,说明找到了一条这样的路径。
public boolean hasPathSum(TreeNode root, int sum) {
        //二叉树为空,返回false
        if (root == null) {
            return false;
        }
        //找到了叶子节点并且符合条件
        if (root.left == null && root.right == null) {
            return (sum == root.val);
        }
        //递归寻找左节点和右节点,此时的sum变成sum-root.val
        return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
    }