题目描述

✅ 14. 最长公共前缀

image-20260928194103451

题意分析

给定一组字符串,找出它们共同拥有的最长开头部分。前缀必须从每个字符串的下标 0 开始,并连续延伸,不能跳过字符,也不能从字符串中间开始寻找。

只要某个位置有字符串结束,或同一位置出现不同字符,公共前缀就不能继续扩展。没有共同的开头时返回空字符串;数组至少包含一个字符串,但其中的字符串可以为空。

解法:纵向逐列比较字符

核心思路

[!blue]

公共前缀一定是第一个字符串的某个前缀,因此可以用它作基准,逐个位置向右尝试扩展,不需要先排序或建立额外的数据结构。

假设已经确认所有字符串的区间 [0, idx) 完全相同。要再加入第 idx 个字符,就必须让每个字符串都存在这个位置,并且该字符都与基准串一致;逐个比较其他字符串即可验证这一条件。

如果发现某个字符串已结束,公共前缀不可能比它更长;如果发现字符不同,任何更长前缀都会包含这一处差异。两种情况都能立即停止,而此前已经确认的 [0, idx) 正好是最长答案,失配位置本身不应包含在返回值中。

如果把基准串完整扫描完仍然一致,它的全部字符都属于公共前缀。又因为任何公共前缀都不可能超过基准串本身,所以直接返回它就是最优结果。基准为空时循环不执行,自然返回空字符串;只有一个字符串时,它本身就是答案。

解题步骤

  1. 取 strs[0] 为基准串 first,从下标 idx = 0 开始扫描。
  2. 对当前位置,依次检查其他字符串:先判断它是否已经结束,再比较字符是否与 first[idx] 相同。
  3. 只要有一串结束或失配,立即返回基准串的左闭右开区间 [0, idx)。
  4. 当前列全部匹配后再检查下一列;若基准串全部扫描完成,返回整个 first。

代码实现

class Solution {
    public String longestCommonPrefix(String[] strs) {
        String first = strs[0];

        for (int idx = 0; idx < first.length(); idx++) {
            char ch = first.charAt(idx);

            for (int i = 1; i < strs.length; i++) {
                // 当前列只要有一个字符串缺失或不同,前缀就在这里结束。
                if (idx == strs[i].length() || strs[i].charAt(idx) != ch) {
                    return first.substring(0, idx);
                }
            }
        }

        return first;
    }
}
func longestCommonPrefix(strs []string) string {
    first := strs[0]
    for idx := 0; idx < len(first); idx++ {
        ch := first[idx]
        for i := 1; i < len(strs); i++ {
            // 同一列出现越界或字符不同,立即返回已确认前缀。
            if idx == len(strs[i]) || strs[i][idx] != ch {
                return first[:idx]
            }
        }
    }
    return first
}

复杂度分析

  • 时间复杂度:$O(S)$,S 为所有字符串的字符总数;遇到失配会提前结束。
  • 空间复杂度:$O(1)$,不计返回字符串,只使用常数个变量。

关键点总结

[!green]

  • 答案一定包含在任意一个输入字符串中,选第一串作为基准就足够。
  • 每次确认一整列,可以保证左边已经匹配的部分始终是所有字符串的公共前缀。
  • 第一处不匹配决定答案终点,后面的字符即使再次相同,也不能越过这处差异继续扩展。

易错点总结

[!yellow]

  • 先读取字符再检查长度,会在遇到较短字符串时越界;代码依靠 || 短路,先判断是否已经结束。
  • 返回区间包含失配位置,会多取一个不属于公共前缀的字符,终点应保持为不包含 idx。
  • 忽略空字符串,会错误地继续比较其他字符串;任意一串为空,公共前缀就只能为空。
  • 失配后继续寻找后面的相同字符,求出的就不再是连续的公共前缀。
  • 本题字符限定为小写英文字母,Go 按字节索引与按字符比较一致。

相似题目

题目 难度 关联与区别
208. 实现 Trie (前缀树) 中等 Trie把相同前缀合并为公共路径,本题只需找到全部字符串共享路径的终点。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/75574694
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!