14. 最长公共前缀(Longest Common Prefix)

难度:简单 | 主题:字符串——纵向扫描

题目

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

示例:

 
strs = ["flower","flow","flight"] → "fl"
 
strs = ["dog","racecar","car"] → ""
 

思路

先讲个故事:翻译官的共同词汇

你是一群翻译官的词汇顾问。每个翻译官手头有一本自己的词汇表(字符串),你需要找出所有人词汇表开头都一样的最长部分

最笨的办法:把所有词汇表两两对比。聪明的办法:以第一个词汇表为基准,一列一列地检查。如果某个人在第 3 个词就对不上了,公共前缀就是前 3 个词。


引导式推导:从暴力到纵向扫描

第 1 层:两两比较

拿 strs[0] 和 strs[1] 求公共前缀,结果再和 strs[2] 求,依次类推。

第 2 层:纵向扫描(推荐)

以第一个字符串为基准,逐列比较所有字符串的第 i 个字符。遇到不匹配或长度不足时返回前缀。


graph LR

    subgraph 纵向扫描

        A["以 strs[0] 为基准"] --> B["比较所有字符串的第 i 列"]

        B --> C{"都匹配?"}

        C -->|是| D["i++, 继续下一列"]

        C -->|否| E["返回 strs[0][:i]"]

    end

为什么纵向扫描更好? 不需要额外空间存储中间结果,时间 O(S)(S 是所有字符总数),空间 O(1)。


代码

 
def longestCommonPrefix(self, strs):
 
    if not strs:
 
        return ""
 
    for i in range(len(strs[0])):
 
        char = strs[0][i]
 
        for j in range(1, len(strs)):
 
            if i == len(strs[j]) or strs[j][i] != char:
 
                return strs[0][:i]
 
    return strs[0]
 

复杂度

指标解释
时间O(S)S 是所有字符总数,最坏比较所有字符
空间O(1)只用了常数额外变量

实战考量

频率分析

简单题但考细节,约 15% 常会考到,可能融入其他题中(如 URL 路由匹配)。

延伸思考

Q:如果字符串数组很大,内存放不下呢?

A:分块读取,或者排序后只比较相邻的。

Q:最长公共后缀怎么做?

A:翻转所有字符串,然后求最长公共前缀。

Q:多个字符串的最长公共子序列?

A:动态规划,二维扩展(1143最长公共子序列)。

易错点

  • 空数组返回 ""

  • 忘记 i == len(strs[j]) 的长度检查

  • 返回 strs[0][:i] 不是 [:i+1],因为第 i 个字符已经不匹配了


生活类比

翻译官的共同词汇 → 纵向扫描

你不需要把每个人的词汇表从头到尾比一遍。

只需要一列一列地对齐看——第 1 列都一样,第 2 列都一样……

直到某一列有人对不上,公共前缀就是前面那些列。

对齐比较,逐列排除——这就是字符串处理的基本功。


相关题目

题目关系
28找出字符串中第一个匹配项的下标字符串匹配
242有效的字母异位词字符串比较
415字符串相加字符串处理基本功

→ 返回题单:LeetCode学习路线图 > 二、字符串

速记卡(面试闪卡)

Q1:一句话讲清「14. 最长公共前缀(Longest Common Prefix)」到底是什么?

A:以首字符串为基准逐列对齐,找出所有字符串开头相同的最长部分。

Q2:一、题目与公共前缀 —— 怎么理解?

A:像翻译官对齐几本词汇表,找所有人开头都一样的最长词。不存在则返回空串,答案就是纵向都一致的头部(Longest Common Prefix)。

Q3:二、纵向扫描思路 —— 怎么理解?

A:像列一列对齐看,第 1 列全同、第 2 列全同……直到某列有人对不上就停。以首串为基准逐列比,无需存中间结果(Vertical Scan)。

Q4:三、代码实现 —— 怎么理解?

A:像拿首串当尺子,外层走每个字符、内层比每串同列,不匹配就切回前缀。别忘了长度检查 i==len(strs[j])(Column Compare)。

Q5:四、复杂度与易错点 —— 怎么理解?

A:像把每个字符摸一遍,时间 O(S) 空间 O(1)。易错在空数组返回 ""、返回 [:i] 不是 [:i+1](Time/Space Complexity)。

Q6:核心速记主线有哪些?

  • 以第一个字符串为基准,逐列纵向比较

  • 某列不匹配或长度不足即返回前缀

  • 时间 O(S) 空间 O(1),优于两两比较

  • 易错:空数组返回"",返回[:i]不是[:i+1]

口诀

A:前缀看开头,

逐列对齐走;

一列对不上,

前面就是头。

相关链接