LeetCode面试150——14最长公共前缀

题目难度:简单

默认优化目标:最小化平均时间复杂度。

Python默认为Python3。

目录

[1 题目描述](#1 题目描述)

[2 题目解析](#2 题目解析)

[3 算法原理及代码实现](#3 算法原理及代码实现)

[3.1 横向扫描](#3.1 横向扫描)

[3.2 纵向扫描](#3.2 纵向扫描)

[3.3 分治](#3.3 分治)

[3.4 二分查找](#3.4 二分查找)

参考文献


1 题目描述

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

复制代码
输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2:

复制代码
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

提示:

  • 1 <= strs.length <= 200

  • 0 <= strs[i].length <= 200

  • strs[i] 仅由小写英文字母组成

2 题目解析

输入一个字符串数组strs,输出strs中各单词的最长公共前缀。strs[i]表示第i个单词。暴力求解的方法是,选定strs[0],然后和strs[1]比较,找到它们的最长公共前缀。然后和strs[2]比,找到它们的最长公共前缀,依次类推。设strs的长度为n,单词的长度为m,平均时间复杂度为O(mn)。

3 算法原理及代码实现

3.1 横向扫描

即暴力求解法。依次遍历每个数组中的每个字符串,对于每个遍历到的字符串,更新最长公共前缀,当遍历完所有的字符串后,即可得到字符串数组中的最长公共前缀。

有一个特殊情况,如果最长公共字符串为空,直接返回即可,无需继续遍历。

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

cpp 复制代码
class Solution {
public:
    // 主函数:找到字符串数组中的最长公共前缀
    string longestCommonPrefix(vector<string>& strs) {
        // 如果字符串数组为空,返回空字符串
        if (strs.empty()) {
            return "";
        }
​
        // 初始化最长公共前缀为第一个字符串
        string maxCommonPrefix = strs[0];
        int n = strs.size();
​
        // 遍历字符串数组,从第二个字符串开始
        for (int i = 1; i < n; i++) {
            // 更新最长公共前缀
            maxCommonPrefix = longestCommonPrefix(maxCommonPrefix, strs[i]);
            // 如果最长公共前缀为空,提前退出循环
            if (maxCommonPrefix.empty()) {
                break;
            }
        }
        
        return maxCommonPrefix;
    }
​
    // 辅助函数:找到两个字符串的最长公共前缀
    string longestCommonPrefix(const string& str1, const string& str2) {
        int n=min(str1.size(),str2.size());
        int index=0;
​
        while(index<n && str1[index]==str2[index]){
            index++;
        }
​
        return str1.substr(0,index);
    }
};
复制代码

Python代码实现

python 复制代码
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        n=len(strs)
        maxCommenPrefix=strs[0]
​
        if not strs:
            return ""
​
        for i in range(1,n):
            maxCommenPrefix=self.MCP(maxCommenPrefix,strs[i])
            if not maxCommenPrefix:
                break
​
        return maxCommenPrefix
​
    def MCP(self, str1, str2) -> str:
        n=min(len(str1),len(str2))
        index=0
​
        while index<n and str1[index]==str2[index]:
            index+=1
​
        return str1[:index]

3.2 纵向扫描

我们换个角度看strs,将每个单词纵向排列在一起,然后从前往后扫描每一列,直到每一列的字母不完全相同时停止。

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

cpp 复制代码
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int n=strs.size();
        int m=strs[0].size();
​
        if(!n){
            return "";
        }
​
        for(int i=0;i<m;i++){
            char c=strs[0][i];
            for(int j=1;j<n;j++){
                if(i == strs[j].size() || c!=strs[j][i]){
                    return strs[0].substr(0,i);
                }
            }
        }
​
        return strs[0];
​
    }
};

Python代码实现

python 复制代码
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs:
            return ""
        
        n = len(strs)
        m = len(strs[0])
        
        for i in range(m):
            c = strs[0][i]
            for j in range(1, n):
                if i == len(strs[j]) or strs[j][i] != c:
                    return strs[0][:i]
        
        return strs[0]
复制代码

3.3 分治

根据横向扫描,有如下数学公式

其中,是字符串的最长公共前缀,

因此,我们可以取,对于

平均时间复杂度为O(mn),平均空间复杂度为O(1)。

C++代码实现

cpp 复制代码
class Solution {
public:
    // 主函数:找到字符串数组中的最长公共前缀
    string longestCommonPrefix(vector<string>& strs) {
        // 如果字符串数组为空,返回空字符串
        if (strs.empty()) {
            return "";
        } else {
            // 使用分治法找到最长公共前缀
            return longestCommonPrefix(strs, 0, strs.size() - 1);
        }
    }
​
    // 辅助函数:使用分治法找到字符串数组中的最长公共前缀
    string longestCommonPrefix(const vector<string>& strs, int start, int end) {
        // 如果只有一个字符串,返回该字符串
        if (start == end) {
            return strs[start];
        } else {
            // 计算中间位置
            int mid = (start + end) / 2;
            // 递归找到左半部分的最长公共前缀
            string lcpLeft = longestCommonPrefix(strs, start, mid);
            // 递归找到右半部分的最长公共前缀
            string lcpRight = longestCommonPrefix(strs, mid + 1, end);
            // 合并左右两部分的最长公共前缀
            return commonPrefix(lcpLeft, lcpRight);
        }
    }
​
    // 辅助函数:找到两个字符串的最长公共前缀
    string commonPrefix(const string& lcpLeft, const string& lcpRight) {
        int minLength = min(lcpLeft.size(), lcpRight.size());
        // 比较两个字符串的字符,找到公共前缀
        for (int i = 0; i < minLength; ++i) {
            if (lcpLeft[i] != lcpRight[i]) {
                return lcpLeft.substr(0, i);
            }
        }
        return lcpLeft.substr(0, minLength);
    }
};
​

Python代码实现

python 复制代码
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs:
            return ""
        else:
            return self.longestCommonPrefixHelper(strs, 0, len(strs) - 1)
​
    def longestCommonPrefixHelper(self, strs, start, end):
        if start == end:
            return strs[start]
        else:
            mid = (start + end) // 2
            lcpLeft = self.longestCommonPrefixHelper(strs, start, mid)
            lcpRight = self.longestCommonPrefixHelper(strs, mid + 1, end)
            return self.commonPrefix(lcpLeft, lcpRight)
​
    def commonPrefix(self, lcpLeft, lcpRight):
        minLength = min(len(lcpLeft), len(lcpRight))
        for i in range(minLength):
            if lcpLeft[i] != lcpRight[i]:
                return lcpLeft[:i]
        return lcpLeft[:minLength]
​

3.4 二分查找

最长公共共前缀不会超过最短长度的单词,用minLength表示最短长度单词。在[0,minLength]之间使用二分查找。

平均时间复杂度为O(mn log m),平均空间复杂度O(1)。

C++代码实现

cpp 复制代码
class Solution {
public:
    // 函数用于找到字符串数组中的最长公共前缀
    string longestCommonPrefix(vector<string>& strs) {
        // 如果输入的字符串数组为空,返回空字符串
        if (!strs.size()) {
            return "";
        }
        
        // 找到数组中最短字符串的长度
        int minLength = min_element(strs.begin(), strs.end(), [](const string& s, const string& t) {return s.size() < t.size();})->size();
        
        int low = 0, high = minLength;
        
        // 使用二分查找法寻找最长公共前缀
        while (low < high) {
            int mid = (high - low + 1) / 2 + low;
            if (isCommonPrefix(strs, mid)) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
        
        // 返回最长公共前缀
        return strs[0].substr(0, low);
    }
​
    // 辅助函数用于检查给定长度的前缀是否是所有字符串的公共前缀
    bool isCommonPrefix(const vector<string>& strs, int length) {
        string str0 = strs[0].substr(0, length);
        int n = strs.size();
        
        // 比较每个字符串的前缀与第一个字符串的前缀
        for (int i = 1; i < n; i++) {
            string str = strs[i];
            for (int j = 0; j < length; j++) {
                if (str0[j] != str[j]) {
                    return false;
                }
            }
        }
        return true;
    }
};
​

Python代码实现

python 复制代码
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs:
            return ""
        
        minLength = min(len(s) for s in strs)
        low, high = 0, minLength
        
        while low < high:
            mid = (high - low + 1) // 2 + low
            if self.isCommonPrefix(strs, mid):
                low = mid
            else:
                high = mid - 1
        
        return strs[0][:low]
​
    def isCommonPrefix(self, strs: List[str], length: int) -> bool:
        str0 = strs[0][:length]
        for i in range(1, len(strs)):
            if strs[i][:length] != str0:
                return False
        return True
复制代码

参考文献

力扣面试经典150题

力扣官方题解

相关推荐
John_ToDebug2 小时前
浏览器扩展延迟加载优化实战:如何让浏览器启动速度提升50%
c++·chrome·windows
是娇娇公主~2 小时前
C++ 中 std::deque 的原理?它内部是如何实现的?
开发语言·c++·stl
2401_874732532 小时前
为你的Python脚本添加图形界面(GUI)
jvm·数据库·python
Fly Wine2 小时前
Leetcode之有效字母异位词
算法·leetcode·职场和发展
FreakStudio2 小时前
0 元学嵌入式 GUI!保姆级 LVGL+MicroPython 教程开更,从理论到实战全搞定
python·单片机·嵌入式·面向对象·电子diy
程序员夏末4 小时前
【LeetCode | 第七篇】算法笔记
笔记·算法·leetcode
小江的记录本4 小时前
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
java·数据库·分布式·后端·sql·spring·面试
luanma1509804 小时前
PHP vs C++:编程语言终极对决
开发语言·c++·php
寂静or沉默4 小时前
2026最新Java岗位从P5-P7的成长面试进阶资源分享!
java·开发语言·面试
剑穗挂着新流苏3124 小时前
117_PyTorch 实战:利用训练好的模型进行单张图片验证
人工智能·python·深度学习