地址 https://leetcode-cn.com/problems/6eUYwP/
一道树的遍历,求树中一个子树,其权值为指定值。
暴力做法
对树进行遍历,计算所有子树的求和。每遍历一个节点,计算所有 以 该节点和其父节点组成的子树的权值,并进行比较这里通过一个数组去保存所有的权值。然后去遍历其孩子。
遇到的坑
- ArrayList对元素的修改
当数组中元素是对象时,存储的是句柄,可以直接对值进行修改。但当元素是Integer 或int时,get得到元素后,再修改是无效的。这里用到arrayist.set(index,value)的api实现修改。 - 数组为空
日常忘记判断,传入的对象需要先判断null
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int count = 0;
int targe ;
public int pathSum(TreeNode root, int targetSum) {
targe = targetSum;
f(root,new ArrayList());
return count;
}
public void f(TreeNode root ,ArrayList<Integer> list){
if(root == null)
return;
Integer val = root.val;
list.add(0);
for(int i=0;i<list.size();i++){
list.set(i, list.get(i)+ val);
if(list.get(i) == targe){
count ++;
}
}
if(root.left != null){
f(root.left,list);
}
if(root.right != null){
f(root.right,list);
}
list.remove(val);
for(int i=0;i<list.size();i++){
list.set(i, list.get(i)- val);
}
}
}
前缀和
和暴力做法有点相似。暴力中用数组记录了每条路径的权重,需要动态增加和删除。这里通过前缀和来记录。
为了描述方便,将树退化为数组,也可以认为是考虑树中某一条路径。
5-4-3 ,5是root,3是叶子。
5-4-3 从root 到叶子
0-5-9-12 # 前缀和
当目标是7时,对应的子树是4-3,那么这条路径的补就是5。 当遍历到“3”时,前缀和是12,如果在路径中存在一段路径权重为5,那么必然存在一段路径,且以3结尾,权重为7。我们要去找的就是当前路径的补。
class Solution {
HashMap<Integer,Integer> map = new HashMap();
int count = 0;
public int pathSum(TreeNode root, int targetSum) {
int cur =0;
map.put(0,1);// baozheng root
f(root,cur,targetSum);
return count;
}
public void f(TreeNode root ,int cur,int targetSum){
if(root == null)
return;
cur += root.val;
count += map.getOrDefault(cur-targetSum,0);// !!!
map.put(cur,map.getOrDefault(cur,0)+1);// !!!
f(root.left,cur,targetSum);
f(root.right,cur,targetSum);
map.put(cur,map.getOrDefault(cur,0)-1);
}
}