1. 程式人生 > >由字符串反轉(使用遞歸)引申出來一道Java面試題

由字符串反轉(使用遞歸)引申出來一道Java面試題

條件 ide rdquo 地方 方式 們的 即使 href 什麽

如何面試一個從事編程工作的開發人員既困難又乏味,幸好還有很多值得參考的指南,比如:《Joel Guerilla Guide to interviewing》,但最後雇傭與否,還得由你自己決定。為了快速地了解他們的編程能力,我想到了一個關於字符串反轉的問題,有人用這道題取得不錯的效果,這道題的答案有很多種,因此這給了你足夠的空間去考察候選者的技能,我自己思考了會兒,找到好幾種答案如何用Java實現字符串的反轉。候選者的答案正好是面試官了解他們如何思考的一種方式。你可以用相關的接口來定義這道題,裏面有一個未實現的方法。


public interface Reverser {  
       public String reverse(String str);   
}   
`

在Java中,最好的實現就是用JDK中StringBuffer的反轉方法,它不僅速度快,效率高,而且還知道如何處理unicode代理對(surrogate pairs)。其它方案基本上都可以忽略掉。


public class JdkReverser implements Reverser {   
       public String reverse(String str) {  
            if ((null == str) || (str.length() <= 1)) {
                return str;  
            }   
            return new StringBuffer(str).reverse().toString();  
        }   
}

不僅選擇把趣味性地實現當做一種答案,而且候選者有沒有重用JDK,或者告訴你“JDK中有那麽些東西是可以去實現的”,哪一種好呢,google一下可以幫你找到JDK的解決方案,你總不希望開發者實現一切。

處理問題:

問他代碼中什麽地方有bug,即使沒有。或者代碼怎麽會報錯,他的答案至少可以引出一個討論關於如何處理空值的話題來。

返回null 返回“” 拋出NullPointerException 拋出IllegalArgumentException

第二個討論的焦點是是如何去優化解決方法,像返回字符串本省“”,長度為1的字符串(本省就是反轉)

遞歸(Recursion):

之後要求應聘者在反轉的問題上寫一個遞歸的方案(這至少是漂亮的,但至少可用)


public String reverse(String str) {  
           if ((null == str) || (str.length()  <= 1)) {  
               return str;  
           }  
           return reverse(str.substring(1)) + str.charAt(0);  
       }

有些開發人員在腦海中想不到處理遞歸,或者需要時間和一些提示。那些不能處理遞歸的很有可能對於復雜的問題沒法完成。

你可以問他們關於遞歸方案的效率,詢問尾(Tail)遞歸,詢問 “+”操作的效率,如何處理,關於為什麽String都是不可變的(至少在大多時候這麽問),反轉“Stephan”時,問候選者有多少個字符串對象創建。在討論中,開發者說“Easy”,他在整個大學都在用Lisp語言,之前我還不知道,現在聽起來真是個極好的消息。你還可以詢問在上面代碼結束遞歸的停止條件。

更多的方案:

在適當的位置調動StringBuffer:


public String reverse(String str) {   
            if ((null == str) || (str.length()  <= 1 )) {  
                return str;   
            }  
            StringBuffer result = new StringBuffer(str);  
            for (int i = 0; i < (str.length() / 2); i++) {  
                int swapIndex = str.length() - 1 - i;  
                char swap = result.charAt(swapIndex);  
                result.setCharAt(swapIndex, result.charAt(i));  
                result.setCharAt(i, swap);  
            }   
            return result.toString();  
        }
采用調用數組的方法:

public String reverse(String str) {   
          if ((null == str) || (str.length() <= 1)) {   
              return str;   
          }   
          char[] chars = str.toCharArray();   
          int right = chars.length - 1;   
          for (int left = 0; left < right; left++) {  
              char swap = chars[left];   
              chars[left] = chars[right];  
              chars[right--] = swap;   
          }   
          return new String(chars);  
      }   

SringBuffer追加的方法:

public String reverse(String str) {   
          if ((null == str) || (str.length() <= 1)) {   
              return str;   
          }    
          StringBuffer reverse = new StringBuffer     (str.length());   
          for (int i = str.length() - 1; i >= 0; i--) {
            reverse.append(str.charAt(i));   
          }   
          return reverse.toString();   
      }  
  }

也許候選人還知道棘手的XOR swapping solution方法。

這是一個開放性的領域,你可以要求候選者寫一個JUnit 測試它的反轉方法,這樣不僅可以展現他寫測試單元的能力,而且作為測試用例,他所考慮的條件(“”,null,”A”,奇數長度的字符串,偶數長度的字符串,….)

在你決定是否雇用時,希望以上能幫上你,對自己來說,在將來的某個時候希望同樣可以我幫助到自己,就像Joel說的:“疑人不用,用人不疑(when in doubt ,always no hire)。”

英文原文:Codemonkeyism
編譯:劉誌軍
譯文鏈接: http://www.importnew.com/501.html

由字符串反轉(使用遞歸)引申出來一道Java面試題