#14 字符串模拟 简单

最长公共前缀

在 LeetCode 上查看 ↗

🎧 语音讲解

开车或通勤时可听,跟着思路走一遍

速度

📋 题目描述

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

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

示例 1

输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2

输入:strs = ["dog","racecar","car"]
输出:""
输入不存在公共前缀。

💭 模拟答题者思考

1. 暴力:枚举所有可能的前缀长度,对每个长度检查是否每个字符串都以该前缀开头——能过,但重复比较很多。

2. 找重复:公共前缀就是「所有串开头相同的最长一段」,每多一个串,只需看当前候选前缀还能不能匹配。

3. 横向扫描:用 strs[0] 当初始 prefix,依次与后面每个串比对;不匹配就不断砍掉 prefix 最后一位,直到匹配或变空。

4. 另一种等价思路是纵向扫描:固定列下标 i,看所有串第 i 个字符是否都与 strs[0][i] 相同,一旦某串更短或字符不同就停。

5. 还可排序后只比首尾串,或建字典树;本题数据规模下横向/纵向扫描 O(S)(S 为所有字符总数)最直观。

🧠 变量语义(先读这三句再编码)

变量类型语义(三句法)
prefixstr定义:当前已确认、所有已处理字符串共同拥有的前缀
维护:初始为 strs[0],每引入一个新串就按需缩短
更新:若 s 不以 prefix 开头,则 prefix = prefix[:-1] 直到匹配或为空
sstr定义:当前正在与 prefix 比对的字符串
维护:按顺序遍历 strs[1:]
更新:每轮取下一个字符串;若 prefix 已空可提前结束
iint定义(纵向扫描写法):当前比对的字符列下标
维护:从 0 开始,以 strs[0][i] 为基准字符
更新:所有串在位置 i 字符一致则 i++,否则停止;答案为 strs[0][:i]

⌨️ 落码步骤

1. 特判空数组;令 prefix = strs[0]

2. 遍历 strs[1:] 中每个字符串 s

3. 当 prefix 非空且 s 不以 prefix 开头时,prefix = prefix[:-1]

4. 若 prefix 已空,提前返回 ""

5. 全部比对完毕,返回 prefix

💻 代码实现

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs:
            return ""
        prefix = strs[0]          # 当前公共前缀候选
        for s in strs[1:]:
            # 不匹配就缩短前缀,直到 s 以 prefix 开头或 prefix 为空
            while prefix and not s.startswith(prefix):
                prefix = prefix[:-1]
            if not prefix:
                return ""
        return prefix
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if (strs.empty()) return "";
        string prefix = strs[0];
        for (int k = 1; k < (int)strs.size(); ++k) {
            const string& s = strs[k];
            while (!prefix.empty() && s.compare(0, prefix.size(), prefix) != 0) {
                prefix.pop_back();
            }
            if (prefix.empty()) return "";
        }
        return prefix;
    }
};
// 时间 O(S),空间 O(1)(不计输入)

📈 复杂度分析

时间复杂度 O(S)
空间复杂度 O(1)

⚠️ 常见坑

不能用 min(len(strs)) 直接当答案长度——还要保证每个位置字符都相同,不能只比长度。

纵向扫描时注意某串长度不足时 i 会越界,应先判断 i < len(s)

空数组要返回 "";单元素数组应返回该元素本身(即整个字符串)。

🔍 必测边界 Case

Case 1:有公共前缀
["flower","flow","flight"] → "fl"
Case 2:无公共前缀
["dog","racecar","car"] → ""
Case 3:单元素 / 空前缀
["a"] → "a"["ab","a"] → "a"(较短串决定上限)