给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例: 给定如下二叉树,以及目标和 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);
}