14. Longest Common Prefix
Title
編寫一個(gè)函數(shù)來查找字符串?dāng)?shù)組中的最長公共前綴。
如果不存在公共前綴,返回空字符串 “”。
Solve
1.橫向掃描
用LCP(S1 …Sn)表示字符串S1 …Sn的最長公共前綴,可以得到以下結(jié)論:LCP(S1…Sn)=LCP(LCP(LCP(S1,S2),S3),…Sn)LCP(S_1…S_n)=LCP(LCP(LCP(S_1,S_2),S_3),…S_n)LCP(S1?…Sn?)=LCP(LCP(LCP(S1?,S2?),S3?),…Sn?)
依次遍歷字符串?dāng)?shù)組中的每個(gè)字符串,對(duì)于每個(gè)遍歷到的字符串,更新最長公共前綴,當(dāng)遍歷完所有的字符串以后,即可得到字符串?dāng)?shù)組中的最長公共前綴。
優(yōu)化: 如果在尚未遍歷完所有的字符串時(shí),最長公共前綴已經(jīng)是空串,則最長公共前綴一定是空串,因此不需要繼續(xù)遍歷剩下的字符串,直接返回空串即可。
Code
def longestCommonPrefix_transverseScan(self, strs: List[str]) -> str:def lcp(str1, str2):index, length = 0, min(len(str1), len(str2))while index < length and str1[index] == str2[index]:index += 1return str1[: index]if not strs:return ""prefix = strs[0]for i in range(1, len(strs)):prefix = lcp(prefix, strs[i])if not prefix:breakreturn prefix時(shí)間復(fù)雜度
- 時(shí)間復(fù)雜度: O(mn),其中m是字符串?dāng)?shù)組中的字符串的平均長度,n是字符串的數(shù)量,最壞情況下,字符串?dāng)?shù)組中的每個(gè)字符串的每個(gè)字符都會(huì)被比較一次。
- 空間復(fù)雜度: O(1),使用額外空間復(fù)雜度為常數(shù)。
2.縱向掃描
縱向掃描時(shí),從前往后遍歷所有字符串的每一列,比較相同列上的字符是否相同,如果相同則繼續(xù)對(duì)下一列進(jìn)行比較,如果不相同則當(dāng)前列不再屬于公共前綴,當(dāng)前列之前的部分為最長公共前綴。
↓↓ flower↓↓ flow↓↓ flightCode
def longestCommonPrefix_longitudinalScan(self, strs: List[str]) -> str:if not strs:return ""for i in range(len(strs[0])):char = strs[0][i]for j in range(1, len(strs)):if i == len(strs[j]) or strs[j][i] != char:return strs[0][:i]return strs[0]時(shí)間復(fù)雜度
- 時(shí)間復(fù)雜度: O(mn),其中m是字符串?dāng)?shù)組中的字符串的平均長度,n是字符串的數(shù)量,最壞情況下,字符串?dāng)?shù)組中的每個(gè)字符串的每個(gè)字符都會(huì)被比較一次。
- 空間復(fù)雜度: O(1),使用額外空間復(fù)雜度為常數(shù)。
3.分治法
LCP 的計(jì)算滿足結(jié)合律,可以有以下推導(dǎo):LCP(S1…Sn)=LCP(LCP(S1,…Sk),LCP(Sk+1,…Sn))LCP(S_1…S_n)=LCP(LCP(S_1,…S_k),LCP(S_{k+1},…S_n))LCP(S1?…Sn?)=LCP(LCP(S1?,…Sk?),LCP(Sk+1?,…Sn?))
基于上述推導(dǎo),可以使用分治法得到字符串?dāng)?shù)組中的最長公共前綴。
對(duì)于問題 LCP(Si ?Sj),可以分解成兩個(gè)子問題 LCP(Si…Smid) 與 LCP(Smid+1?…Sj),其中 mid= (i+j)/2,對(duì)兩個(gè)子問題分別求解,然后對(duì)兩個(gè)子問題的解計(jì)算最長公共前綴,即為原問題的解。
Code
def longestCommonPrefix_divideAndConquer(self, strs: List[str]) -> str:def lcp(left, right):if left == right:return strs[left]middle = (left + right) // 2leftLcp, rightLcp = lcp(left, middle), lcp(middle + 1, right)minLength = min(len(leftLcp), len(rightLcp))for i in range(minLength):if leftLcp[i] != rightLcp[i]:return leftLcp[:i]return leftLcp[: minLength]return "" if not strs else lcp(0, len(strs) - 1)時(shí)間復(fù)雜度
- 時(shí)間復(fù)雜度: O(mn),其中m是字符串?dāng)?shù)組中的字符串的平均長度,n是字符串的數(shù)量。時(shí)間復(fù)雜度的遞推式是T(n)=2T(n/2)+O(m),通過計(jì)算可得 T(n)=O(mn)。
- 空間復(fù)雜度: O(mlogn),其中 m 是字符串?dāng)?shù)組中的字符串的平均長度,n 是字符串的數(shù)量。空間復(fù)雜度主要取決于遞歸調(diào)用的層數(shù),層數(shù)最大為 logn,每層需要 m 的空間存儲(chǔ)返回結(jié)果。
4.Python內(nèi)置函數(shù)
zip() 函數(shù)用于將可迭代的對(duì)象作為參數(shù),將對(duì)象中對(duì)應(yīng)的元素打包成一個(gè)個(gè)元組,然后返回由這些元組組成的列表。
如果各個(gè)迭代器的元素個(gè)數(shù)不一致,則返回列表長度與最短的對(duì)象相同,利用 * 號(hào)操作符,可以將元組解壓為列表。
def longestCommonPrefix_python(self, strs: List[str]) -> str:for index, value in enumerate((*(len(set(item)) for item in zip(*strs)), 2)):if value > 1:return (*strs, "")[0][: index]總結(jié)
以上是生活随笔為你收集整理的14. Longest Common Prefix的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的地盘我做主——你必须遵守的Pytho
- 下一篇: 297. Serialize and D