问题描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”
示例
输入:[“flower”,“flow”,“flight”]
输出:“fl”
解法一:水平扫描法
算法描述:
首先,将列表中的字符串按照长度重新排序,然后依次遍历字符串
,首先求
,然后求
,依次类推:
Python3实现
def longestCommonPrefix(strs):
if len(strs) == 0:
return ""
else:
strs = sorted(strs, key=len)
prefix = strs[0]
for i in range(1,len(strs)):
while strs[i].find(prefix) != 0:
prefix = prefix[0:len(prefix)-1]
if len(prefix) == 0:
return ""
return prefix
解法二:分治法
算法描述
这个算法的思路来自于LCP操作的结合律。 我们可以发现:
,其中
是字符串
的最长公共前缀,
。
为了应用上述的结论,我们使用分治的技巧,将原问题
分成两个子问题
与
。
其中mid =
。 我们用子问题的解 lcpLeft 与 lcpRight 构造原问题的解。 从头到尾挨个比较 lcpLeft 与 lcpRight 中的字符,直到不能再匹配为止。 计算所得的 lcpLeft 与 lcpRight 最长公共前缀就是原问题的解。
Python3实现
def longestCommonPrefix(strs):
def recursion(strs, l, r):
if l == r:
return strs[l]
else:
mid = (l+r)//2
lcpLeft = recursion(strs, l, mid)
lcpRight = recursion(strs, mid+1, r)
return commonPrefix(lcpLeft,lcpRight)
def commonPrefix(left, right):
while right.find(left) != 0:
left = left[0:len(left)-1]
if len(left) == 0:
return ""
return left
if len(strs) == 0:
return ""
else:
return recursion(strs, 0, len(strs)-1)
解法三:二分查找法
算法描述
应用二分查找法找到所有字符串的公共前缀的最大长度 L。 算法的查找区间是
,其中 minLen 是输入数据中最短的字符串的长度,同时也是答案的最长可能长度。 每一次将查找区间一分为二,算法进行的过程中一共会出现两种可能情况:
-
S[1…mid] 不是所有串的公共前缀。 这表明该前缀加上mid后面的字符也一定不是公共前缀,于是我们就可以丢弃后半个查找区间。
-
S[1…mid] 是所有串的公共前缀。 这表示该前缀加上mid后面的字符有可能也是公共前缀,因为我们要找最长的公共前缀,所以我们将mid后的字符附加在S[1…mid]后继续进行匹配。
Python3实现
def longestCommonPrefix(strs):
def isCommonPrefix(strs, length):
for i in range(1,len(strs)):
if strs[i].find(strs[0][0:length+1]) == 0:
continue
else:
return False
return True
if len(strs) == 0:
return ""
else:
strs = sorted(strs, key=len)
low, high = 0, len(strs[0])-1
while low <= high:
mid = (low + high) // 2
if isCommonPrefix(strs, mid):
low = mid + 1
else:
high = mid - 1
print ((low + high) // 2)
return strs[0][0:(low + high) // 2 + 1]