1、背景:
變位詞指的是一個單詞可以通過改變其他單詞中字母的順序來得到,也叫做兄弟單詞,如army->mary。
題1:判斷兩個字符串s1和s2是否為變位詞。
經典的字符串變位詞檢測問題是比較不同數量級函數算法的一個典型例子。如果一個字符串是 另一個字符串的重新排列組合,那么這兩個字符串互為變位詞。比如,”heart”與”earth”互為變位 詞,”python”與”typhon”也互為變位詞。為了簡化問題,我們設定問題中的字符串長度相同,都是由 26 個小寫字母組成。我們需要編寫一個接受兩個字符串,返回真假,代表是否是一對變位詞的布爾 函數。
法①:檢查標記【時間復雜度為O(n2)】
思路:檢查第一個字符串中的所有字符是不是都在第二個字符串中出現。 如果能夠把每一個字符都“檢查標記”一遍,那么這兩個字符串就互為變位詞。檢查標記一個字符 要用特定值 None 來代替,作為標記。然而,由於字符串不可變,首先要把第二個字符串轉化成一個列表。第一個字符串中的每一個字符都可以在列表的字符中去檢查,如果找到,就用 None 代替以示標記。
def anagram(s1,s2): s2=list(s2) still_ok=True i=0 while i<len(s1) and still_ok: found=False j=0 while j<len(s2) and not found: if s1[i]==s2[j]: Found=True else: j+=1 if found: s2[j]==None else: still_ok=False i+=1 return still_ok
法②:排序比較【時間復雜度為O(n2)】
思路:盡管 s1 和 s2 並不相同,但若為變位詞它們一定包含完全一樣的字符,利用這一特點,我們可以 采用另一種方法。我們首先從 a 到 z 給每一個字符串按字母順序進行排序,如果它們是變位詞,那么 我們將得到兩個完全一樣的字符串。此外,我們可以先將字符串轉化為列表,再利用 Python 中內建
的 sort 方法對列表進行排序。下面代碼展示了這種方法。
第一眼看上去你可能會認為這個算法的復雜度是 O(n),畢竟排序后只需要一個簡單的循環去比較 n 個字符。然而對 Python 內建的 sort 方法的兩次使用並非毫無消耗。事實上,正如我們在后面的章節 中將要看到的,排序方法的復雜度往往都是 O(n²)或者 O(n㏒n),所以排序貢獻了這個函數主要的循 環操作。最終,這個算法和排序的復雜度相同。
def anagram(s1,s2): s2=list(s2) s1=list(s1) list_s1=sorted(s1) list_s2=sorted(s2) still_ok=True i=0 while i<len(list_s1): if list_s1[i]==list_s2[i]: still_ok=True else: still_ok=False i+=1 return still_ok
法③:計數比較法【時間復雜度O(n)】
解決變位詞問題的最后一個方法利用了任何變位詞都有相同數量的 a,相同數量的 b,相同數量 的 c 等等。為判斷兩個字符串是否為變位詞,我們首先計算每一個字符在字符串中出現的次數。由於
共有 26 個可能的字符,我們可以利用有 26 個計數器的列表,每個計數器對應一個字符。每當我們 看到一個字符,就在相對應的計數器上加一。最終,如果這兩個計數器列表相同,則這兩個字符串 是變位詞。下面展示了這種方法:
def anagram(s1,s2): counter1=[0]*26 counter2=[0]*26 for i in s1: counter1[ord(i)-ord('a')]+=1 for i in s2: counter2[ord(i)-ord('a')]+=1 if counter1==counter2: return True else: return False