路经总和
DFS
深搜,如果搜到叶子结点时,此路径符合:找到;不符合:回溯
这里注意public boolean hasPathSum(TreeNode root, int targetSum) 此方法一开始传进来的就是sum,因此可以每往下走到下一结点,sum–,判断叶子结点处是否为0,而不是在根处sum=0,每次加结点值
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
//边界值
if(root==null){
return false;
}
//走到叶子结点的时候判断
if(root.left==null && root.right==null){
return targetSum-root.val==0;
}
//非叶子结点 左右 取并集
return hasPathSum(root.left,targetSum-root.val) || hasPathSum(root.right,targetSum-root.val);
}
}
BFS
解需要遍历二叉树,遍历考虑DFS BFS
BFS:使用队列
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
Queue<TreeNode>q = new LinkedList<TreeNode>();
if(root!=null)
q.add(root);
TreeNode t;
while(!q.isEmpty()){
t = q.poll();
if(t.left==null && t.right==null && t.val==targetSum){
return true;
}
if(t.left!=null){
t.left.val += t.val;
q.add(t.left);
}
if(t.right!=null){
t.right.val += t.val;
q.add(t.right);
}
}
return false;
}
}
113. 路径总和 II
记录路径
class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> path = new ArrayList<Integer>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
dfsPath(root,targetSum);
return res;
}
public void dfsPath(TreeNode root,int targetSum){
if(root==null){
return ;
}
path.add(root.val);
targetSum -= root.val;
if(root.left==null && root.right==null && targetSum==0){
res.add(new ArrayList<Integer>(path));
}
dfsPath(root.left,targetSum);
dfsPath(root.right,targetSum);
//target不用加回来
path.remove(path.size()-1); //很奇怪 用LinkedList的remoteLast不可以
}
}
路径三
class Solution {
Map<Integer,Integer>mp = new HashMap<>(); //mp[3] = 2 前缀和为2的路径总共有两条
public int pathSum(TreeNode root, int targetSum) {
mp.put(0,1);
return dfs(root,0,targetSum);
}
public int dfs(TreeNode root,int curSum,int targetSum){
if(root==null){
return 0;
}
curSum += root.val; //走到当前节点 此时的前缀值
//考虑之前走过的加上本节点 长度为当前前缀和目标值的差的路有多少条
//当前结点是最后一个结点的情况
int now = mp.getOrDefault(curSum-targetSum,0);
mp.put(curSum,mp.getOrDefault(curSum,0)+1); //当前前缀值是cursum 记录到mp中
int left = dfs(root.left,curSum,targetSum);
int right = dfs(root.right,curSum,targetSum);
//状态恢复: 在遍历完一个节点的所有子节点后,将其从map中除去。
//比如AB结点是root的左右孩子 遍历完A后 put进了A中有的前缀和 那么再遍历B时,能拿到A的前缀和 但是这不是从根节点一直往下得到的 因此要删掉
mp.put(curSum,mp.get(curSum)-1); //当前前缀值是cursum 记录到mp中
return now+left+right;
}
}
注意超范围
class Solution {
Map<Long,Long>mp = new HashMap<>(); //mp[3] = 2 前缀和为2的路径总共有两条
public int pathSum(TreeNode root, int targetSum) {
mp.put(0L,1L);
return (int)(dfs(root,0L,targetSum));
}
public long dfs(TreeNode root,long curSum,long targetSum){
if(root==null){
return 0;
}
curSum += root.val; //走到当前节点 此时的前缀值
//考虑之前走过的加上本节点 长度为当前前缀和目标值的差的路有多少条
//当前结点是最后一个结点的情况
Long now = mp.getOrDefault(curSum-targetSum,0L);
mp.put(curSum,mp.getOrDefault(curSum,0L)+1); //当前前缀值是cursum 记录到mp中
long left = dfs(root.left,curSum,targetSum);
long right = dfs(root.right,curSum,targetSum);
//状态恢复: 在遍历完一个节点的所有子节点后,将其从map中除去。
//比如AB结点是root的左右孩子 遍历完A后 put进了A中有的前缀和 那么再遍历B时,能拿到A的前缀和 但是这不是从根节点一直往下得到的 因此要删掉
mp.put(curSum,mp.get(curSum)-1); //当前节点不影响其他兄弟结点 只影响其孩子结点
return now+left+right;
}
}