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