题目
给定一个二叉树root和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径。
1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n
例如:
给出如下的二叉树, sum=22,
返回true,因为存在一条路径 5→4→11→25→4→11→2的节点值之和为 22
数据范围:
1.树上的节点数满足 0≤n≤10000
2.每 个节点的值都满足 ∣val∣≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(树的高度),时间复杂度 O(n)
示例1
输入:{5,4,8,1,11,#,9,#,#,2,7},22
返回值:true
示例2
输入:{1,2},0
返回值:false
示例3
输入:{1,2},3
返回值:true
示例4
输入:{},0
返回值:false
思路1:递归
代码1
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @param sum int整型
* @return bool布尔型
*/
public boolean hasPathSum (TreeNode root, int sum) {
if(root == null){
return false;
}
if(root.left == null && root.right == null && sum - root.val == 0){
return true;
}
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
}
思路2:栈+深度优先搜索(dfs)
知识点1:栈
栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
知识点2:深度优先搜索(dfs)
深度优先搜索一般用于树或者图的遍历,其他有分支的(如二维矩阵)也适用。它的原理是从初始点开始,一直沿着同一个分支遍历,直到该分支结束,然后回溯到上一级继续沿着一个分支走到底,如此往复,直到所有的节点都有被访问到。
在二叉树中能够用递归解决的问题,很多时候我们也可以用非递归来解决。这里遍历过程也可以使用栈辅助,进行dfs(深度优先搜索)遍历,检查往下的路径中是否有等于sum的路径和。
注意,这里仅是dfs,而不是前序遍历,左右节点的顺序没有关系,因为每次往下都是单独添加某个节点的值相加然后继续往下,因此左右节点谁先遍历不管用。
具体做法:
- step 1:首先检查空节点,空树没有路径。
- step 2:使用两个栈同步遍历,一个栈记录节点,辅助深度优先搜索,另一个栈跟随记录到该节点为止的路径和。根节点及根节点值先进栈。
- step 3:遍历的时候每次弹出两个栈中的内容,判断是否是叶子节点且路径和是否等于目标值。
- step 4:没有到叶子节点就将左右子节点(如果有)加入栈中,并跟随加入路径和。
- step 5:如果遍历结束也没有找到路径和,则该二叉树中没有。
代码2
import java.util.*;
public class Solution {
public boolean hasPathSum (TreeNode root, int sum) {
//空节点找不到路径
if(root == null) {
return false;
}
//栈辅助深度优先遍历
Stack<TreeNode> s1 = new Stack<TreeNode>();
//跟随s1记录到相应节点为止的路径和
Stack<Integer> s2 = new Stack<Integer>();
s1.push(root);
s2.push(root.val);
while(!s1.isEmpty()){
//弹出相应节点
TreeNode temp = s1.pop();
//弹出到该点为止的当前路径和
int cur_sum = s2.pop();
//叶子节点且当前路径和等于sum
if(temp.left == null && temp.right == null && cur_sum == sum) {
return true;
}
//左节点及路径和入栈
if(temp.left != null){
s1.push(temp.left);
s2.push(cur_sum + temp.left.val);
}
//右节点及路径和入栈
if(temp.right != null){
s1.push(temp.right);
s2.push(cur_sum + temp.right.val);
}
}
return false;
}
}