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.
题目是让找出给定一个数组中所有字符串的最长相同前缀。
首先想到的是遍历其中所有的字符串,每次都找出最长的前缀,然后这个前缀接着与剩下的字符串进行比较,当相同的前缀为空时则跳出来,结束算法。当输入为空时直接输出‘’即可。
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if len(strs) == 0:
return ''
strs = sorted(strs,key=lambda xx:len(xx))
temp = strs[0]
for i in range(len(strs)-1):
minlen = len(temp)
if minlen == 0:
break
temp = [tm for tm in temp]
nextvalue = [tm for tm in strs[i+1][:minlen]]
for k in range(minlen):
if temp[k] != nextvalue[k]:
temp = temp[:k]
break
if len(temp) == 0:
return ''
else:
re = ''
for xx in temp:
re = re + xx
return re
因为最长的前缀至多等于最短的字符串。所以先对其进行了排序,进而能够减少一些冗余的计算量。
第二种想法就是对所有的字符串进行按列的比较,直到出现列中存在不相同的列后就跳出算法。
#utilize the column to find same prefix
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
r = [len(set(c)) == 1 for c in zip(*strs)] + [False]
return strs[0][:r.index(False)] if strs else ''
这段代码巧妙的利用了zip函数,能够直接对列表中所有字符串按顺序进行分裂到一个元组中,然后再利用集合判断是不是该集合中只含有一个元素,若是含有多个元素就证明出现了不一样的前缀了,即前面的为最长的前缀了。该可以再进一步的改进一下就是当检测到了有不同的字母时就跳出算法:
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
flag = 0
for c in zip(*strs):
if len(set(c)) != 1:
break
flag += 1
return strs[0][:flag] if strs else ''
第三种想法就是利用函数sort()进行排序,而排序之后的输出第一个元素和最后一个元素是相差最大的两个元素,故只需要找出这两个元素的最长前缀即可。
class Solution:
def longestCommonPrefix(self, s: List[str]) -> str:
if not s:
return ""
s.sort()
n = len(s)
a = s[0]
b = s[n-1]
res = ""
for i in range(len(a)):
if i < len(b) and a[i] == b[i]:
res += a[i]
else:
break
return res
这个算法的时间复杂度和空间复杂度是最低的,并且鲁棒性也较好。
这道题中学习到了,zip(*strs)一个巧妙的用法以及set相互结合的用法可以很大的提高代码的简洁性,还有函数sort对字符串排序操作之后的特性,以及在算法中需要考虑到一些特殊的情况,如输入是空列表[]时,应该单独的考虑一下。