题目描述

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。

LeetCode原题地址:https://leetcode-cn.com/problems/longest-common-prefix/

测试用例

  • 示例 1

输入: [“flower”,“flow”,“flight”]
输出: “fl”

  • 示例 2

输入: [“dog”,“racecar”,“car”]
输出: “”

解释: 输入不存在公共前缀。
说明:所有输入只包含小写字母 a-z 。

代码实现

  • 横向比较

字符串之间进行比较,求最长前缀公共子串,其实就是再求列表中所有字符串的前缀交集。所以,我们可以一个字符串一个字符串的比较。

第一个字符串与第二个字符进行比较求解最长前缀公共子串,得到的最长前缀公共子串再与下一个字符串进行比较,以此类推。如果在比较的过程中出现了最长前缀公共子串出现了空串就直接结束,因为空串与任何字符串的公共子串都为空。

class Solution:
    def lcp(self,s1,s2):
        """计算两个字符串的最长公共自创
        :param s1:
        :param s2:
        :return:
        """
        #最长公共子串的长度不会超过短的字符串
        s_len = min(len(s1),len(s2))
        index = 0
        while index < s_len:
            if s1[index] == s2[index]:
                index += 1
            else:
                break
        return s1[:index]

    def longestCommonPrefix(self, strs: list) -> str:
        if len(strs) == 0:
            return ""
        #将列表第一个字符串赋值为最长公共子串
        com_prefix = strs[0]
        for s in strs[1:]:
            #计算最长公共子串与后面字符串的公共子串
            com_prefix = self.lcp(com_prefix,s)
            #如果最长公共子串为空,直接结束比较
            if len(com_prefix) == 0:
                return ""
        return com_prefix

solution = Solution()
print(solution.longestCommonPrefix(["dog","racecar","car"]))
  • 纵向比较

按列比较列表中每个字符串中的每个字符是否相等,如果下标超过字符串长度或比较的字符不相等就直接结束比较

class Solution:
    def longestCommonPrefix(self, strs) -> str:
        if len(strs) == 0:
            return ""
        #遍历第一个字符串
        for i in range(len(strs[0])):
            com_prefix_c = strs[0][i]
            #遍历后面的字符串
            for s in strs[1:]:
                #如果字符串的长度小于i或公共字符不相等
                #就直接结束比对
                if len(s) <= i or com_prefix_c != s[i]:
                    return strs[0][:i]

solution = Solution()
print(solution.longestCommonPrefix(["flower","flow","flight"]))
  • 递归法求解

将字符列表对半拆分,一级一级拆分下去来求解最长前缀公共子串

python求公共字符 python 公共子字符串_公共子串

class Solution:
    def lcp(self,l,r):
        if l == r:
            return self._strs[l]
        m = (l+r) // 2
        l_s,r_s = self.lcp(l,m),self.lcp(m+1,r)
        min_len = min(len(l_s),len(r_s))
        for i in range(min_len):
            if l_s[i] != r_s[i]:
                return l_s[:i]
        return l_s[:min_len]

    def longestCommonPrefix(self, strs) -> str:
        self._strs = strs
        if len(strs) == 0:
            return ""
        return self.lcp(0,len(strs)-1)
  • 二分法

二分法的解题思路是,先计算出字符串列表中最小字符串的长度,然后再比较前一半的字符串是否相等,如果不相等,就比较前一半的一半,相等就比较前一半再增加后一半的一半,以此类推进行比较。

python求公共字符 python 公共子字符串_最长公共子串_02

class Solution:
    def is_common_prefix(self,index):
        com_prefix = self._strs[0][:index]
        return all(s[:index]==com_prefix for s in self._strs[1:])

    def longestCommonPrefix(self, strs) -> str:
        self._strs = strs
        if len(strs) == 0:
            return ""
        min_s_len = min(len(s) for s in strs)
        low = 0
        high = min_s_len - 1
        while low < high:
            mid = low + (high-low+1) // 2
            if self.is_common_prefix(mid):
                low = mid
            else:
                high = mid - 1
        return strs[0][:low]


solution = Solution()
print(solution.longestCommonPrefix(["flower","flow","flight"]))

参考:

  1. LeetCode解题思路