Leetcode014 最长公共前缀

这次的题,没有特别好的思路,就是个双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]):
还有这种函数,又长知识了!以上。

猜你喜欢

转载自blog.csdn.net/u014292401/article/details/80947371
今日推荐