题目描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
思路
我的思路很简单,先将第一个字符串整体作为最长公共前缀,与后面的字符串依次进行比较,不断调整公共前缀,当前缀的长度减少到0的时候,就说明没有公共前缀。
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
f = strs[0]
n = len(f)
for s in strs[1:]:
if s[:n] != f:
if n == 1:
return ""
for i in range(1, n):
if s[:n-i] == f[:n-i]:
n = n-i
f = s[:n]
break
if n-i == 1:
return ""
return f
题解
方法一:横向扫描
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs:
return ""
prefix, count = strs[0], len(strs)
for i in range(1, count):
prefix = self.lcp(prefix, strs[i])
if not prefix:
break
return prefix
def lcp(self, str1, str2):
length, index = min(len(str1), len(str2)), 0
while index < length and str1[index] == str2[index]:
index += 1
return str1[:index]
其实我的思路就是横向扫描,只是具体实现方法有一些不同而已。
方法二:纵向扫描
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs:
return ""
length, count = len(strs[0]), len(strs)
for i in range(length):
c = strs[0][i]
if any(i == len(strs[j]) or strs[j][i] != c for j in range(1, count)):
return strs[0][:i]
return strs[0]
所谓纵向扫描,与横向的区别就是:从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。
这两种扫描的方法的复杂度是相同的:
时间复杂度:O(mn)
空间复杂度:O(1)
方法三:分治
分治的思路从下图就可以看出。
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
def lcp(start, end):
if start == end:
return strs[start]
mid = (start + end) // 2
lcpLeft, lcpRight = lcp(start, mid), lcp(mid + 1, end)
minLength = min(len(lcpLeft), len(lcpRight))
for i in range(minLength):
if lcpLeft[i] != lcpRight[i]:
return lcpLeft[:i]
return lcpLeft[:minLength]
return "" if not strs else lcp(0, len(strs) - 1)
时间复杂度:O(mn)
空间复杂度:O(mlogn)
虽然这种方法的空间复杂度比前两种高,但这种思想还是值得学习的。
方法四:二分查找
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
def isCommonPrefix(length):
str0, count = strs[0][:length], len(strs)
return all(strs[i][:length] == str0 for i in range(1, count))
if not strs:
return ""
minLength = min(len(s) for s in strs)
low, high = 0, minLength
while low < high:
mid = (high - low + 1) // 2 + low
if isCommonPrefix(mid):
low = mid
else:
high = mid - 1
return strs[0][:low]
时间复杂度:O(mnlogm)
空间复杂度:O(1)