在blogspot上看到一個十分有趣的字符串算法題目,作者講述了自己面試google的一次經歷。本文不理會這個故事,只來討論一下里面着個有趣的算法。
算法題目:有兩個字符串由不同的字母組成,一長一短,長的爲A短的爲B。設計一個算法,如果所有在B中出現的字符都在A中出現,則返回true,否則返回false。
例子:
如下字符串:
字符串A: abddfdioegdddffsfagj
字符串B: dofsjadg
字符串B中每個字符都在A中出現,返回true。
如下字符串:
字符串A: aaaabbbbbbdddddd
字符串B: acc
字符串B中有字符沒在A中出現,返回false。
這只是個很基礎的算法題目,相信很多人都能夠立刻想出答案。
答案1:對字符串B中的每個字母在A中都遍歷一遍。這個答案很爛,其時間複雜度爲O(n*m)
答案2:設一個哈希表,對字符串A的字符遍歷,將每個字符對應的哈希表中的值設爲1。然後對B中的字符進行遍歷,如果所有字符對應的hash值都爲1,則返回true,否則返回false。
這個答案的時間複雜度是O(m+n),應該是大多數面試者想要的答案,相信大多數人也能想到。這樣結束了?如果真結束了,那就談不上有趣了!如果我們對空間要求比較高該怎麼辦?
答案3:我們可以觀察到,字母總共就有26個,而且在上面答案中,hash表的值只有1和0兩種情況。那就好辦了,我們知道int類型是32位,如果用1位(bit)來表示一個字母是否出現,那麼只需1個int類型就能夠表示所有的字母了。
答案3實際上跟答案2類似,換湯不換藥。有趣的不是他,實際上還存在一種更有意思的方法:
答案4:我們爲每個字母(假設字母的數量是一定的)分配一個不重複素數,比如a爲2, b爲3, c爲5,以此類推。這樣在對字符串A進行遍歷時,將每個字符表示的素數相乘,最終得到一個比較大的整數。然後從字符串B中第一個字母開始,用每個字母所代表的數除這個整數,如果餘數不爲0,那麼就返回false。如果整個遍歷過程中都沒有餘數,則返回true。
在我第一次從原文中看到着個答案的時候,有一種眼前一亮的感覺。實際上仔細推敲,這種算法的效率並不一定比之前的答案要高,因爲往往一個乘法/除法的效率要小於加減法或者比較運算。但是卻給出了一種全新的考慮問題的角度,有種奇思妙想的感覺!這種方法更爲巧妙,有趣!
在每個算法題目中,你在得到一個公認的比較有效的方法後,是否考慮過更簡單、有趣的方法呢?