2011-10-25 73 views
1

以下哪一项是反转字符串中单词的有效方法?哪些代码更有效?

public String Reverse(StringTokenizer st){ 
    String[] words = new String[st.countTokens()]; 
    int i = 0; 
    while(st.hasMoreTokens()){ 
     words[i] = st.nextToken();i++} 

    for(int j = words.length-1;j--) 
     output = words[j]+" ";} 

OR

public String Reverse(StringTokenizer st, String output){   
    if(!st.hasMoreTokens()) return output;   
     output = st.nextToken()+" "+output; 
     return Reverse(st, output);}  

public String ReverseMain(StringTokenizer st){  
    return Reverse(st, "");} 

而第一种方式似乎更具可读性和直接的,也有它两个循环。在第二种方法中,我尝试过使用尾递归的方法。但我不确定java是否会优化尾递归代码。

+1

找出问题的最佳方法是分析代码并查看哪些代码运行得更快。 – NickLH

+0

请参见http://stackoverflow.com/questions/771092/is-method-a-faster-than-method-b – paxdiablo

+0

'StringTokenizer'不被弃用,但是... * StringTokenizer是一个遗留类,由于兼容性原因而被保留尽管它在新代码中的使用不受欢迎。建议任何需要此功能的人都使用String或java.util.regex包的拆分方法*(来自java文档) –

回答

2

你能做到这一点,在短短一个循环

public String Reverse(StringTokenizer st){ 
    int length = st.countTokens(); 
    String[] words = new String[length]; 
    int i = length - 1; 
    while(i >= 0){ 
     words[i] = st.nextToken();i--} 
} 
2

但我不确定java是否确实优化了尾递归代码。

它没有。由约翰·罗斯@甲骨文


我不知道这是否让一个解决方案比其他快。 (自己测试......注意避免标准的微基准陷阱)

但是,Java没有实现tail-call优化的事实意味着第二个解决方案可能会用尽堆栈空间如果你给它一个带有大量(足够)单词的字符串。


最后,如果你正在寻找实现这样的空间效率更高的方式,存在使用只是一个StringBuilder聪明的办法。

  1. 从输入String
  2. 创建 StringBuilder
  3. 使用reverse()反向的StringBuilder的字符。
  4. 逐步通过StringBuilder,标识每个单词的开始和结束偏移量。对于每个起始/结束偏移对,反转偏移之间的字符。 (您必须使用循环执行此操作。)
  5. StringBuilder转回String
+0

所以第二个解决方案是有风险的,那么我看到 那么递归的用途究竟是什么呢?只有当我们确信递归方法的输入不会超过某个限制才能导致堆栈溢出时,它才有用吗? 因此,如果你在java中编程,使得你的recruive调用是否是尾递归是没有意义的?尾递归主要用于函数式语言吗?谢谢 – comatose

+0

在Java中使用递归时总是需要小心,但这并不意味着你不应该使用它。例如,如果事先知道输入数据结构的大小/形状对递归量有合理的限制,那就好了。未来的Java实现也可能包含尾部呼叫优化。但是,是的,将代码转换为尾递归并不会提高当前代Java的性能。 –

0

您可以通过大量的结果

例如定时两者的测试结果。您反转100000000个字符串并查看需要多少秒。您还可以比较开始和结束系统时间戳,以获得两个函数之间的精确差异。

0

的StringTokenizer不会被弃用,但如果你读取当前的JavaDoc ...

StringTokenizer是一个遗留类,由于兼容性原因而被保留,尽管它在新代码中的使用不受欢迎。建议任何寻求此功能的人使用String或java.util.regex包的拆分方法。

String[] strArray = str.split(" "); 
StringBuilder sb = new StringBuilder(); 
for (int i = strArray.length() - 1; i >= 0; i--) 
    sb.append(strArray[i]).append(" "); 

String reversedWords = sb.substring(0, sb.length -1) // strip trailing space