题目:
给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
示例 1:
输入: [1,2,3]
1
/ \
2 3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.
示例 2:
输入: [4,9,0,5,1]
4
/ \
9 0
/ \
5 1
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495.
从根到叶子节点路径 4->9->1 代表数字 491.
从根到叶子节点路径 4->0 代表数字 40.
因此,数字总和 = 495 + 491 + 40 = 1026.
自己的代码优化过程
思路:
利用数的深度优先遍历方式遍历。每遍历一个节点则StringBuilder拼接上该节点的
值。如果该节点是叶子节点(左子节点和右子节点都为null)。则将拼接后的结果
添加到集合中。最后遍历集合将字符串转为int类型相加求和。
public int sumNumbers(TreeNode root) {
List<String> list = new ArrayList<>();
depthFirstSearchRecursive(root,new StringBuilder(""),list);
int count = 0;
for (String str : list){
count = count + Integer.valueOf(str);
}
return count;
}
private void depthFirstSearchRecursive(TreeNode node,StringBuilder str,List list) {
if (node != null){
str.append(node.val);
if (node.left == null && node.right == null){
list.add(str.toString());
}
depthFirstSearchRecursive(node.left,str,list);//1
depthFirstSearchRecursive(node.right,str,list);//2
}
}
纠错及优化
上面的代码1和2处公用的一个str对象,导致拼接完左叶子节点后的字符串参与了右子节点的拼接。所以重新创建一个str对象。写法优化,将sumNumbers方法中的for循环改成java8写法。
public int sumNumbers(TreeNode root) {
List<String> list = new ArrayList<>();
depthFirstSearchRecursive(root,new StringBuilder(""),list);
int count = 0;
for (String str : list){
count = count + Integer.valueOf(str);
}
return list.stream().mapToInt(Integer :: valueOf).sum();
}
private void depthFirstSearchRecursive(TreeNode node,StringBuilder str,List list) {
if (node != null){
str.append(node.val);
if (node.left == null && node.right == null){
list.add(str.toString());
}
StringBuilder newStr = new StringBuilder(str);
depthFirstSearchRecursive(node.left,str,list);//1
depthFirstSearchRecursive(node.right,newStr,list);//2
}
}
再次优化
问题虽然解决但是效率比较低。分析代码发现在最后for循环遍历求和可以优化成在递
归中返回求和。
public int sumNumbers(TreeNode root) {
return depthFirstSearchRecursive(root,"");
}
private int depthFirstSearchRecursive(TreeNode node,String num) {
if (node == null) return 0;
num = num + node.val;
if (node.left == null && node.right == null){
return Integer.valueOf(num);
}
return depthFirstSearchRecursive(node.left,num) + depthFirstSearchRecursive(node.right,num);
}
进一步优化
发现性能更差了,String类型的拼接和String转int类型比较耗时。直接使用int类型作为
参数类型。
public int sumNumbers(TreeNode root) {
return depthFirstSearchRecursive(root,0);
}
private int depthFirstSearchRecursive(TreeNode node,int num) {
if (node == null) return 0;
num = num * 10 + node.val;//每拼接一个数则前面的数扩大十倍
if (node.left == null && node.right == null){
return num;
}
return depthFirstSearchRecursive(node.left,num) + depthFirstSearchRecursive(node.right,num);
}