Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
return
[
[5,4,11,2],
[5,8,4,5]
]
求二叉树中所有根到叶子节点的值的和等于指定数字的路径
题目不难 注意两种写法的区别
第一种 我写的
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList<>();
pathSum(root, new ArrayList<>(), sum, res);
return res;
}
private void pathSum(TreeNode root, List<Integer> cur, int sum, List<List<Integer>> res) {
if (root == null) return;
cur.add(root.val);
sum -= root.val;
if (root.left == null && root.right == null && sum == 0) {
res.add(new ArrayList<>(cur));
return;
}
pathSum(root.left, new ArrayList<>(cur), sum, res);//1.
pathSum(root.right, new ArrayList<>(cur), sum, res);
}
每次都把当前节点的值加入到cur中 当cur满足和等于sum 添加到结果集res中
平均runtime 6ms
第二种 discuss中看到的 平均runtime 3ms
public List<List<Integer>> pathSum(TreeNode root, int sum) {
if(root == null){
return new ArrayList<>();
}
List<List<Integer>> result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
dfs(root, sum, result, list);
return result;
}
private void dfs(TreeNode node, int sum, List<List<Integer>> result, List<Integer> list){
list.add(node.val);
sum = sum - node.val;
if(node.left == null && node.right == null && sum == 0){
result.add(new ArrayList<>(list));
}
if(node.left != null){
dfs(node.left, sum , result, list);
}
if(node.right != null){
dfs(node.right, sum, result, list);
}
sum = sum + node.val;//1.
list.remove(list.size() - 1);
}
主要区别就是1.处
因为保存当前路径的集合list 后面也在重复利用 为了避免他们的互相产生影响
(比如遍历左子树 右子树 都会向list中添加元素)
有两种解决办法
1.向下传递list的时候 新建一个集合 把list的元素放进去
2.本层递归执行完毕后 把刚才添加进来的元素删掉
我采用的是1 discuss采用的是2
为什么2比较快呢 我一开始以为是
new ArrayList<>(cur);
时间复杂度是O(n), 会把cur中的元素逐一copy进新建的集合 看了list的源码发现不是的
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
因为list的底层实现是Object数组 所以这行代码会直接把新集合的数组替换成cur的数组 时间复杂度O(1)
elementData.getClass() != Object[].class
才会逐个copy慢的原因应该是新建集合的消耗