在技術面試中經常會遇到演算法題,接下來,我計劃(在我的能力範圍內)寫一些常見面試題及其解決思路,希望可以鞏固自己的知識,如果可以順便幫助到一些朋友,就更好不過了。
第一道(也是最簡單的一道)面試題便是:如何確定一個字串中是否所有字元全部互不相同?
在開始完成這道題之前,最好先向出題者確認的一件事情是,這是字串是純ASCII字串還是Unicode字串。這決定了你後續的解題過程,這個問題可以向面試官傳達出你很關注細節,且對電腦科學有一定認識。
這裡假設字符集為ASCII,當然如果是Unicode,只需要擴大記憶體,其他解題思路上基本是一致的。
首先需要想到的是,ASCII只有一個位元組,意味著如果待檢測的字串長度超過了256位,那麼這個字串中一定有重複的元素。解題的方式有很多種,下面列舉幾種常見的解法:
最簡單的解法是將字串中的每一個字元與剩下的字元比較,如果遇到相同的元素,則返回False
,如果直到遍歷結束都沒有遇到相同元素,則返回True
:
1 2 3 4 5 6 7 8 9 10 11 12 |
def is_unique_char(string): str_len = len(string) if str_len > 256: return True for pos in xrange(str_len): for index in xrange(pos+1, str_len): if string[pos] == string[index]: return False return True |
這種解法的時間複雜度為O(n*n)
,空間複雜度為O(1)
。當然很明顯,這種解法的效率非常低下,有什麼更好的實現呢?
第二種解法是通過構建一個布林值的陣列,索引index
表示ASCII碼中值為index
的字元。將初值置為False
,如果某個元素第二次出現,則表示這個字串出現了重複的字元,函式直接返回。這種解法的Python實現如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def is_unique_char(string): if len(string) > 256: return True record = [False] * 256 for ch in string: ch_val = ord(ch) if record[ch_val]: return False record[ch_val] = True return True |
上面程式碼的時間複雜度為O(n)
,空間複雜度為O(1)
。不過,我們可以非常確定的是,n的最大值僅僅為256。
如果使用位運算,結合Python中數字的特殊實現,我們僅需要一個數字來替代record
即可實現上面的演算法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def is_unique_char(string): if len(string) > 256: return True record = 0L for ch in string: print record ch_val = ord(ch) if (record & (1 << ch_val)) > 0: return False record |= (1 << ch_val) return True |
如果允許對字串進行修改,則我們還有一種O(nlog(n))
的演算法來解決這個問題:將字串排序,然後遍歷每一個元素並與周圍元素比較(請自行嘗試)。
如果考慮到Python的某些資料結構,則我們可以通過collections
裡的工具來實現:
1 2 3 |
from collections import Counter is_unique_char = lambda s: True if len(s) > 256 else not bool(filter(lambda n: n > 1, Counter(s).values())) |
這些演算法可能算不上最優解,不過根據題目,我們依次從比較容易的實現向比較複雜的實現再結合Python的集合類,讓出題者瞭解了你的思考過程和對特定語言的工具集的使用。
這應該是面試中最最簡單的演算法題目了,接下來我打算(在我的能力範圍裡)再由淺入深多寫點。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!