Leetcode: Binary Tree Paths 从一道Easy题看Java String链接效率
来源:互联网 发布:好用的vpn 知乎 编辑:程序博客网 时间:2024/05/20 09:47
别说话,快上题!
Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
1 / \2 3 \ 5
All root-to-leaf paths are:
["1->2->5", "1->3"]其实这是一道挺简单的Tree的DFS输出路径的题目,但是题目唯一tricky的地方就是输出。它是要输出一个String类型的list,并不是像往常一样输出一个Integer类型的Array。其实就是一个String的链接嘛。
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */public class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> Result = new ArrayList(); if(root == null){ return Result; } String temp = new String(); pathHelper(root,temp,Result); return Result; } private void pathHelper(TreeNode root, String temp, List<String> Result) { if (root == null){ return; } temp += String.valueOf(root.val); int length = temp.length(); if (root.left == null && root.right == null){ Result.add(temp); return; } pathHelper(root.left,temp + "->",Result); pathHelper(root.right,temp + "->",Result); temp.substring(0,length-1); } }
最后一行是为了确保返递归返回时把上一个解去掉,这样才能找到所有的解。
其实这道题讲究的地方还是挺多的。如果在面试的时候给了这样的解答,会有一个follow up就是如何提高string链接的效率。其实在Java中,String的‘+’操作符是javaJDK中唯一overload的操作符。它其实是完成了append()方法,所以使用‘+’操作符进行字符串链接时效率并没有那么高。
在Thinking in Java的String那章里,作者专门对String的‘+’操作符与StringBuilder中的append()方法的效率进行了一个比较。
public class Concatenation { public static void main(String[] args) {
String mango = "mango"; String s = "abc" + mango + "def" + 47; System.out.println(s);
} } /* Output: abcmangodef47 *///:~
javap -c Concatenation
public static void main(java.lang.String[]); Code:
Stack=2, Locals=3, Args_size=1 0: ldc #2; //String mango
2: astore_1 3: new #3; //class StringBuilder 6: dup 7: invokespecial #4; //StringBuilder."<init>":() 10: ldc #5; // String abc 12 invokevirtual #6; //StringBuilder.append:(String) 15 aload_1 16 invokevirtual #6; //StringBuilder.append:(String) 19 ldc #7; //String def 21 invokevirtual #6; //StringBuilder.append:(String) 24 bipush 47 26 invokevirtual #8; //StringBuilder.append:(I) 29 invokevirtual #9; //StringBuilder.toString:() 32 astore_2 33 getstatic #10; //Field System.out:PrintStream; 36 aload_2 37 invokevirtual #11; // PrintStream.println:(String) 40 return
line 7 12 16 21 26 29我们可以看到 通过invokevirtual命令,编译器调用了JVM中的StringBuilder这个类,但是我们的代码中并没有使用这个类,但是编译器决定这么做,应为StringBuilder的效率更高。
我们再将实验代码换成StringBuilder实现:
//: strings/WhitherStringBuilder.java
public class WhitherStringBuilder { public String implicit(String[] fields) {
String result = ""; for(int i = 0; i < fields.length; i++)
result += fields[i]; return result;
} public String explicit(String[] fields) {
StringBuilder result = new StringBuilder(); for(int i = 0; i < fields.length; i++)
result.append(fields[i]); return result.toString();
}
} ///:~
我们使用Javap -c WithStringBuilder 我们可以比较两个方法的不同之处:
第一个是使用+运算符的。
public java.lang.String implicit(java.lang.String[]); Code:
0: ldc #2; //String 2: astore_2 3: iconst_0 4: istore_3
5: iload_3 6: aload_1 7: arraylength 8: if_icmpge 38 11: new #3; //class StringBuilder 14: dup 15: invokespecial #4; // StringBuilder.”<init>”:() 18: aload_2 19: invokevirtual #5; // StringBuilder.append:() 22: aload_1 23 iload_3 24 aaload 25: invokevirtual #5; // StringBuilder.append:() 28: invokevirtual #6; // StringBuiIder.toString:() 31: astore_2 32: iinc 3, 1 35: goto 5 38: aload_2 39 areturn
接下来是使用StringBuilder的:
public java.lang.String explicit(java.lang.String[]); Code:
0: new #3; //class StringBuilder 3: dup 4: invokespecial #4; // StringBuilder.”<init>”:() 7: astore_2 8: iconst_0 9: istore_3 10: iload_3 11: aload_1 12: arraylength 13: if_icmpge 30 16: aload_2 17: aload_1 18: iload_3 19: aaload 20 invokevirtual #5; // StringBuilder.append:() 23 pop 24: iinc 3,1 27: goto 10 30: aload_2 31: invokevirtual #6; // StringBuiIder.toString:() 34: areturn
可以看到第二个方法,JVM以及编译器会提升很多效率。
在@tianping168博主的文章:http://blog.csdn.net/tianping168/article/details/2458103 中有对于Java各个String链接方式的性能测试。大家有兴趣的可以去看一看。
最后贴一下这道题使用StringBuilder的方法:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */public class Solution { public List<String> binaryTreePaths(TreeNode root) { List<String> Result = new ArrayList(); if (root == null){ return Result; } StringBuilder temp = new StringBuilder(); minHelper(root,temp,Result); return Result; } private void minHelper(TreeNode root, StringBuilder temp, List<String> Result){ if(root == null){ return; } temp.append(String.valueOf(root.val)); int length = temp.length(); if(root.left == null && root.right == null){ Result.add(temp.toString()); return; } if(root.left != null){ minHelper(root.left,temp.append("->"),Result); temp.delete(length,temp.length()); } if(root.right != null){ minHelper(root.right,temp.append("->"),Result); temp.delete(length,temp.length()); } }}
贴个测试时间图 哈哈哈
- Leetcode: Binary Tree Paths 从一道Easy题看Java String链接效率
- Leetcode 257. Binary Tree Paths (Easy) (cpp)
- leetcode 257[easy]-----Binary Tree Paths
- 【一天一道LeetCode】#257. Binary Tree Paths
- Easy 257题 Binary Tree Paths
- LeetCode解题报告 257. Binary Tree Paths [easy]
- [leetcode-257]Binary Tree Paths(java)
- Leetcode:257. Binary Tree Paths(JAVA)
- leetcode-java-257. Binary Tree Paths
- LeetCode-257. Binary Tree Paths (Java)
- Leetcode: Binary Tree Paths
- [LeetCode] Binary Tree Paths
- [Leetcode]Binary Tree Paths
- leetcode:Binary Tree Paths
- [leetcode] Binary Tree Paths
- Leetcode: Binary Tree Paths
- LeetCode:Binary Tree Paths
- leetcode Binary Tree Paths
- 274. H-Index
- poj 2623 快排
- 图像处理之-位图
- Ngnix Tcp 代理转发SS服务
- Android 系统自带样式Android:theme
- Leetcode: Binary Tree Paths 从一道Easy题看Java String链接效率
- 迷茫!前路无尽头
- 在eclipse中将android项目生成apk并且给apk签名
- 随记
- 小谈变量的作用域
- 第三周Android的学习笔记
- 机器学习笔记
- 软硬件调试九法:第三条规则 不要想而要看
- The 3n + 1 problem