最长公共前缀的核心思路是纵向扫描(逐字符对比):
- 以第一个字符串为基准,依次取其第
i个字符; - 遍历数组中其他所有字符串,检查它们的第
i个字符是否与基准字符一致; - 若某一字符串无第
i个字符(长度不足),或字符不一致,则返回前i个字符组成的前缀; - 若所有字符串的第
i个字符都一致,继续检查下一个字符; - 若基准字符串的所有字符都匹配完成,返回基准字符串。
代码实现(Python)
python
运行
def longestCommonPrefix(strs: list[str]) -> str:
# 边界条件:数组为空则返回空字符串
if not strs:
return ""
# 以第一个字符串为基准
base = strs[0]
# 遍历基准字符串的每个字符(按索引)
for i in range(len(base)):
current_char = base[i]
# 检查其他所有字符串的第i个字符
for s in strs[1:]:
# 情况1:当前字符串长度不足i(无第i个字符);情况2:字符不匹配
if i >= len(s) or s[i] != current_char:
# 返回前i个字符的前缀
return base[:i]
# 所有字符都匹配,返回基准字符串
return base
代码解释
-
边界处理:先判断数组是否为空,避免后续索引越界;
-
基准选择:选第一个字符串作为对比基准,简化逻辑;
-
逐字符校验:
-
外层循环遍历基准字符串的每个字符索引
i; -
内层循环遍历数组中其他字符串,检查两个核心条件:
i >= len(s):当前字符串长度不足,无法匹配第i个字符;s[i] != current_char:字符不匹配;
-
满足任一条件则立即返回前
i个字符的前缀;
-
-
完全匹配:若基准字符串的所有字符都通过校验,说明它就是最长公共前缀,直接返回。
测试用例验证
python
运行
# 示例1
print(longestCommonPrefix(["flower","flow","flight"])) # "fl"
# 示例2
print(longestCommonPrefix(["dog","racecar","car"])) # ""
# 额外测试:单元素数组
print(longestCommonPrefix(["apple"])) # "apple"
# 额外测试:部分匹配
print(longestCommonPrefix(["abc","ab","a"])) # "a"
复杂度分析
- 时间复杂度:O (m*n),其中
m是最长公共前缀的长度,n是字符串数组的长度。最坏情况下(所有字符串完全相同),需要遍历所有字符串的所有字符; - 空间复杂度:O (1),仅使用了固定数量的变量,无额外空间消耗。
补充思路(横向扫描)
另一种常见思路是横向对比:先取前两个字符串的公共前缀,再将该前缀与第三个字符串对比,更新公共前缀,依次类推。代码实现如下(供参考):
python
运行
def longestCommonPrefix(strs: list[str]) -> str:
if not strs:
return ""
prefix = strs[0]
for s in strs[1:]:
# 不断缩短前缀,直到找到与当前字符串的公共前缀
while not s.startswith(prefix):
prefix = prefix[:-1]
if not prefix:
return ""
return prefix
两种思路各有优劣:纵向扫描在前缀较短时效率更高(提前终止),横向扫描逻辑更直观。推荐优先使用纵向扫描,更符合 “最长公共前缀” 的逐字符匹配逻辑。