这次的题,没有特别好的思路,就是个双for循环解决。由于检查的是各个单词的公共前缀,有一个不同就不行了,所以就拿第一个单词出来,以它长度为限做外围循环(反正前缀不能超过第一个单词的长度吧,当然对哪个单词都是一样);内层循环字符串列表,检查每个单词的相同内容。查到有不同的前缀内容,就跳出返回,而由于是双for,用了一个flag做标志位来跳出外层循环。
第一次完成的程序如下:
class Solution:
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
index = 0 # 相同前缀的所至的下标
flag = 0 # 标志位,为1的时候说明找到了不同的前缀
word1 = strs[0] #选第一个单词出来
for i in range(len(word1)):
prefix = word1[:i]
for elements in strs:
if prefix != elements[:i]:
flag = 1
break
if flag == 1:
break
index += 1
if index != 0:
return word1[:(index - 1)]
elif index == 0:
return ''
后来想了一下如果检测到不同就返回是不是语句更简洁,但问题是,如果列表里都是一样的单词,不会出现检测不同的地方,两层循环出去了总得有return接着它,所以也就没有再改。
第一次提交运行,报错了。输入是[]的时候out of range……我QNNNGT,空字符串列表输入你妹啊啊啊
给方法在最前边添加了一个判断列表是否为空的判断
第二次提交运行,报错。输入是['']的时候out of range……列表空完,某个字符串还可能是空的,来捣乱砸场子的是吧?
所以提第一个元素,以及后边提每个元素的时候都检查一下这个字符串是不是空的。
第三次提交运行,报错。输入是['a'],输出是''。嗯……这个确实是没想到。只有一个元素的时候,那前缀就它了,不能去跟后边一个比。
所以加个判断,只有一个元素的时候,直接返回这个元素。
第四次提交运行,报错。输入是['c', 'c'],输出也是''。就好好看了一下,原来是自己的列表分片没掌握好。代表位置的数字指的是第几个元素,而不是下标了。我用flower试了一下从头输出,结果是这样的:
y = 'flower'
print(y[:0])
print(y[:1])
print(y[:2])
输出是:
f
fl
这是三行对应三个输出。0是没有指向任何一个字符,是空;1是第一个字符是f;2是第二个字符,用了:2就是前两个字符,是fl。
因此原程序里这部分都错了,所有的带分片的都加1。
第五次提交运行,终于过了。附源代码:
class Solution:
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
if len(strs) == 0:
return ''
elif len(strs) == 1:
return strs[0]
index = 0 # 相同前缀的所至的下标
flag = 0 # 标志位,为1的时候说明找到了不同的前缀
word1 = strs[0] #选第一个单词出来
if word1 == '':
return ''
for i in range(len(word1)):
prefix = word1[:(i+1)]
for elements in strs:
if elements == '':
return ''
if prefix != elements[:(i+1)]:
flag = 1
break
if flag == 1:
break
index += 1
if index != 0:
return word1[:index]
elif index == 0:
return ''
在各种判断和小分片下,程序看着都快支离破碎了。但这么多细节,再次凸显边界、特殊情况的重要性。这么简单的题弄到现在也是醉了
在网上参考了别人写的,一种写法是如下这样:
class Solution:
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
index = 1
if strs == []:
return ""
minlen = min(map(len, strs))
count = 0
while index <= minlen:
jet = 1
for i in strs[1:]:
if not i.startswith(strs[0][:index]):
jet = 0
index -= 1
break
if jet == 0:
break
index += 1
count += 1
if count == 0:
return ""
if index > minlen:
index = minlen
return strs[0][:index]
不能省的细节也都有。说几个自己不会的,没注意到的细节:
1.它用了map便捷的求了list里所有字符串的长度最小值,形式是map(f, list)。网上引得一段话:map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。这是
minlen = min(map(len, strs))
这句话巧妙的地方。
2.循环时也可以用分片,在
for i in strs[1:]:
处,避免了把第一个元素再带入循环进行检查,还是减小了时间复杂度的。
3.判断是不是前缀,作者用了
if not i.startswith(strs[0][:index]):
还有这种函数,又长知识了!以上。