14 - Longest Common Prefix - python

49 阅读2分钟

14. Longest Common Prefix

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.

AC code

  • 线性扫描法:从strs的头开始依次进行比较:

    • 如果strs == [] 或者strs中包含'',直接返回''

    • 如果strs中只有一个元素,则直接返回该元素

    • 如果strs中包含多个元素,依次比较两个相邻的元素,将其最长公共前缀后下一个元素比较,知道到头

      • 如果比较过程中得到的公共前缀为'',直接返回''即可
      • 否则最后返回最长的公共前缀
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        def preFix(str1, str2):
            l = str1 if len(str1) <= len(str2) else str2
            for i in range(len(l)):
                if str1[i] != str2[i] and i == 0:
                    return ''

                if str1[i] != str2[i]:
                    return l[:i]
                if str1[i] == str2[i] and i == len(l) - 1:
                    return l
               

        if strs == [] or '' in strs:
            return ''

        if len(strs) == 1 and '' not in strs:
            return strs[0]

        res = []
        longPreFix = strs[0]
        res.append(longPreFix)
        for s in strs[1:]:
            p = preFix(longPreFix, s)
            if p == '':
                res.pop()
                res.append('')
                return res[0]
            elif len(p) < len(res[0]):
                res.pop()
                res.append(p)

        return res[0]

线性扫描法需要不断的进行两两比较,虽然设置了中断条件,但是复杂度仍较高。根据题目的描述,最长公共前缀是指每个元素的前 k , k = 0 , . . . , m i n ( l e n ( s ) ) k, k = 0,...,min(len(s)) k,k=0,...,min(len(s))个相同的字符, k + 1 k+1 k+1处的就不同了。因此,我们可以直接比较每个元素每一列的字符,如果该列字符都相同,则继续往后比较,知道到了最短的元素的长度为止;如果到某一列存在不同的字符,则它之前的字符串为最长公共前缀。而python内置的zip函数就可以很方便的提取list中每个元素相同索引处的元素,实现代码如下:

# 利用zip()来比较每一列上的元素,使用set()进行去重后,如果个数为1说明该列上字符都相同;否则存在不同字符,终止算法
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:     
        s = ""
        for i in zip(*strs):
            if len(set(i)) == 1:
                s += i[0]
            else:
                break           
        return s 

source:leetcode14 - Longest Common Prefix题解

zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

a = [1,2,3]
b = [4,5,6]
zipped = zip(a,b)  # 打包为元组的列表,元素个数与最短的列表一致
# [(1, 4), (2, 5), (3, 6)]
zip(*zipped)  # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
# [(1, 2, 3), (4, 5, 6)]

使用zip构造字典

key = ['a', 'b', 'c']
value = [1, 2, 3]
d = {}
for k, v in zip(key, value):
	d[k] = v

矩阵行列互换

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print (list(zip(*a)))
print (list(map(list, zip(*a))))
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]