浙大python判断两个字符串是否为变位词_python数据结构与算法 变位词
變位詞
問題簡述
“變位詞”判斷問題:所謂 "變位詞" 是指兩個詞之間存在組成字母的重新排列關系,例如 Heart 和 Earth,python 和 typhon,為了簡單起見,假設參與判斷的兩個詞僅由小寫字母組成,而且長度相等
解題目標
? 寫一個 bool 函數,以兩個詞作為參數,返回這兩個詞是否為變位詞
意義
? 用于展示解決統一問題的不同數量級的算法的差距
解法一:逐字檢查
? 假設要檢查的字符串記為 A 和 B,一個很顯然的思路是把 A 中的每一個字符都到 B 中去檢查看是否存在,如果存在就“打勾”(以防重復檢查),如果每個字符都能找到,則兩個詞是變位詞,但凡有 1 個字符找不到,就不是變位詞
? 思路很簡單,但這里面有個小細節:應該如何實現“打勾”呢?其實很簡單,只需要給抹掉,下一次就不會再檢索到它了,然而字符串并非可變類型,所以我們需要 list 來做中轉,下面給出具體實現和詳細注釋:def anagramSolution(s1,s2):
s_list = list(s2) # 將第二個字符串轉為可變類型list
pos1 = 0 # 用來遍歷第一個字符串的指針
stillOk = True # 只要有一個沒找到,就不是變位詞
while pos1 < len(s1) and stillOk: # 因為s1和s2的長度一定是一樣的,所以直接遍歷s1
pos2 = 0 #遍歷第二個列表字符串的指針
found = False # 一開始當然是什么都沒有找到
while pos2 < len(s_list) and not found: # 拿著s1的第一個元素檢查s2中的每一個
if s1[pos1] == s_list[pos2]: #如果發現一樣的元素
found = True #說明找到了一個
else: # 如果沒找到
pos2 = pos2 + 1 # 看下一個
if found: # 如果找到了
s_list[pos2] = None # 抹掉
else: # 但凡有一個沒找到
stillOk = False # 就不需要繼續了
pos1 = pos1 + 1 # 取出s1中的下一個元素繼續檢查s2
return stillOk # 返回結果
解法一:算法分析
問題的規模:
? 詞中包含的字符個數 n
最耗時的部分:
? 兩重循環,這里不給出推導過程,數量級為 n 的平方
解法二:排序比較
? 首先將兩個字符串都按照字母順序排好序,只要構成元素相同,最后排完序的結果一定也是相同的,我們只需要檢查兩個字符串是否相同就可以了,相同則是變位詞,不相同則不是變位詞
? 如何排序?這里我們直接引用 python 中 list 提供的方法sort直接進行排序,它可以直接修改原有的 list
? 我們來看具體實現,仍然比較簡單:def anagramSolution(s1,s2):
alist1 = list(s1)
alist2 = list(s2) #先把兩個字符串都轉化為list
match = True # 用來檢查兩個list是否相同
pos = 0 # 同步檢測兩個list的對應位置
alist1.sort()
alist2.sort() # 為兩個列表排好序
while pos < len(alist1) and match: # 這一段是檢查兩個列表是否完全相同
if alist1[pos] == alist2[pos]:
pos = pos + 1
else: # 只要有一個不相同
match = False # 就是不匹配
return match
解法二:算法分析
? 可以看到,改進過的算法比原有的方法簡潔的多, 那么時間復雜度如何呢?
復雜度分析
? 粗看過去,改進過的算法似乎只有一個循環,最多執行 n 次
? 但是,在循環之前的兩個 sort并非沒有任何代價,它的運行時間數量級約為 n 倍的 log n,大于循環所執行的 n
? 因此,本算法中最耗時的部分應為排序過程,時間復雜度為 n log n
解法三:計數比較
? 對比兩個詞中每個字母出現的次數,如果 26 個字母出現的次數都相同的話,這兩個字符串一定是變位詞
? 為每個詞設置一個 26 位的計數器,先檢查每個詞,在計數器中設定好每個字母出現的次數
? 計數器完成后,進入比較階段,看兩個字符串的計數器是否相同,如果相同則輸出是變位詞的結論
? 下面給出代碼演示:def anagramSolution(s1,s2):
c1 = [0]*26
c2 = [0]*26 #分別設置計數器
for i in range(len(s1)):
pos = ord(s1[i])-ord('a') # ord表示轉化為編碼,來計算出在計數器中的偏移位置
c1[pos] = c1[pos] + 1 #對應位置計數器累加
for i in range(len(s2)): # 對另一個也做相同的操作
pos = ord(s2[i])-ord('a')
c2[pos] = c2[pos]+1
j = 0 # 從這里開始比較兩個計數器是否相同,和上面的解法一樣
stillOk = True
while j < 26 and stillOk:
if c1[j] == c2[j]:
j = j + 1
else:
stillOk = False
return stillOk
解法三:算法分析
? 雖然看起來有三個循環,但可以發現并非嵌套的循環,最后一次循環是比較計數器,其時間是固定的,所以算法復雜度是 2n + 26,其數量級為 n,是三個算法中性能最好的
小結
? 解決相同問題時合理的算法優化可以顯著提高性能
總結
以上是生活随笔為你收集整理的浙大python判断两个字符串是否为变位词_python数据结构与算法 变位词的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 水滴石穿C语言之typedef的问题
- 下一篇: C++中直接存取类私有成员[360度]