一.问题描述
Write a function to find the longest common prefix string amongst an array of strings.
If there is no common prefix, return an empty string ""
.
Example 1:
Input: ["flower","flow","flight"] Output: "fl"
Example 2:
Input: ["dog","racecar","car"] Output: "" Explanation: There is no common prefix among the input strings.
Note:
All given inputs are in lowercase letters a-z
.
二.解题思路
常规思路时间复杂度是O(mn),m是strs中最短的字符串的长度,n是strs的长度。
也可以用二分法来做。
首先是常规思路:
就是首先找到strs中的最短字符串,然后迭代最小字符串的每个字符,判断这个字符在其他所有字符串中的同样位置是否也是该字符,是的话添加这个字符到结果字符串中,不是的话直接返回。
至于实现的话,可以利用zip函数将strs拆分,strs中所有同样位置的字符组成一个元组(zip函数生成的元组长度等于最小字符串的长度,元素个数与最短的列表一致)。这样子代码很简洁,但是注意简洁不意味着快,zip函数还是比较耗时的。
二分法思路:
有些人说这是O(nlogm),但是我觉得还是O(mn),就最后运行效果来说也是。
就是找到了最小字符串,然后每次比较这个最小的字符串的一半是不是和其他所有字符串最相应位置相同,相同的话就比较另一半。
为什么说我觉得还是O(mn)呢,首先你最外层循环是logM这是没问题的,但是logM里面判断一半的字符串是否相等并不是O(1),而是O(len(一半字符串)),它不想我们从一个有序数组中找一个数,判断是否舍弃另一半是O(1)操作,所以最后综合来说还是O(N)。具体看代码就知道了。
更多leetcode算法题解法: 专栏 leetcode算法从零到结束 或者 leetcode 解题目录 Python3 一步一步持续更新~
三.源码
1.常规思路非zip函数
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
n,res=len(strs),""
if n==0:return res
shortest=min(strs,key=lambda x:len(x))
for i in range(len(shortest)):
if self.isContained(strs,i,shortest): res+=shortest[i]
else:break
return res
def isContained(self,strs,pos,shortest):
res=True
for i in range(len(strs)):
if strs[i][pos]!=shortest[pos]:return False
return res
2.常规思路zip函数,来自:https://leetcode.com/problems/longest-common-prefix/discuss/447698/Python-Best-Solution
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
res=""
for i in list(zip(*strs)):
if len(set(i))==1:
res+=i[0]
else:
break
return res
3.二分法,来自:https://leetcode.com/problems/longest-common-prefix/discuss/447079/Python-O(lg-n)-solution
class Solution(object):
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
if not strs:
return ''
if len(strs) == 1:
return strs[0]
min_length = len(strs[0])
for item in strs[1:]:
if len(item) < min_length:
min_length = len(item)
# min_length - length of the shortest string
min = 0
max = min_length
while max - min > 1: # O(logM)
med = int((max + min) / 2)
prefix = strs[0][:med]
mismatch = False
for item in strs[1:]:
if prefix != item[:med]: # O(med) not O(1)
mismatch = True
break
if mismatch:
max = med
else:
min = med
if mismatch:
return strs[0][:min]
else:
return strs[0][:max]
f=Solution().longestCommonPrefix
f(["flower","flow","flight"])