2011-10-25 72 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