题目描述
求字符串数组的最长公共前缀,没有则返回空串。
思路解析
最朴素的想法是把字符串两两去比公共开头、再取交集,既要反复比较、又纠结"拿哪个词当基准"。其实有更清爽的办法:直接竖着对齐、一列一列检查。
为什么成立:公共前缀必然是每一列上所有词都相同的那段连续字符。所以拿第 0 个词当基准,逐列(第 0 列、第 1 列……)检查其余词的同位字符是否都和基准一样;只要有一个不同、或某个词已到头,就立刻停,前面对齐的部分就是答案。
准备 · 以首词 "flower" 逐列:下面用基准词 "flower" 演示。列指针 cur 指向第 0 列,准备检查其余词在这一列上和基准是否一致。
第 0 列 · 三词都是 f ✓:第 0 列:flow 的首字母是 f、flight 也是 f,和基准 flower 的 f 都一样。这一列纳入公共前缀,cur 前移。
第 1 列 · 三词都是 l ✓:第 1 列:三个词都是 l,仍然一致。公共前缀长到 "fl"。cur 继续前移到第 2 列。
第 2 列 · cur 前移,准备比较:前两列都一致,cur 前移到第 2 列。基准 flower 这一位是 o,接下来逐个看其余词在这一列是不是也都是 o。
第 2 列 · 先比 flow:先看 flow,flow[2] 也是 o,和基准对得上,暂时还没分歧。继续看下一个词 flight。
第 2 列 · flight 不一致(负例):转折:再看 flight,flight[2] 是 i,和基准的 o 不相等!这一列出现分歧——立刻停下,不再往后看。这就是负例:一列不齐即止。
另一种停因 · 某词到头:补充另一种负例(本例没触发):如果某个词比基准短,扫到它长度之外的列时,它根本没有该位字符,也必须停——前缀不能超过最短的词。下标越界要和"字符不同"一样当作停止条件。
结果 · 公共前缀 "fl":在第 2 列断开,截取基准词已对齐的前 2 位:"fl",就是最长公共前缀。
"公共前缀"的直觉就是把多个词竖着摞起来、一列一列对齐,第一处不齐就是边界。这种"纵向对齐"思路在很多多字符串问题里都能复用。
参考代码(Python)
1if not strs: return class="cl-str">""
2for i in range(len(strs[0])): # i = 列号(动画里的 cur)
3 c = strs[0][i] # 基准词该列字符
4 for s in strs[1:]: # 其余词逐个比该列
5 if i >= len(s) or s[i] != c: # 到头 或 不同 → 停
6 return strs[0][:i] # 前面对齐的就是答案
7return strs[0] # 全程没断 → 首词即公共前缀复杂度分析
- 时间复杂度:O(总字符数) —— 最坏把每个词每个字符都看一遍,记作 S
- 空间复杂度:O(1) —— 只用列指针与结果,不开额外结构
套路模板
记住骨架:以首词逐列、其余词比该列、越界或不等就截断返回。简单可靠,是处理"多个字符串共同部分"的常用方法。
1for i in range(len(strs[0])): # 逐列
2 for s in strs[1:]: # 其余词比该列
3 if i >= len(s) or s[i] != strs[0][i]: # 越界 或 不等
4 return strs[0][:i] # 第一处不齐即截断
5return strs[0]易错点
- 错误写法:只比字符、不判某词是否到头 → 正确写法:加上 i >= len(s) 一起当停止条件(前缀不能超过最短的词,漏判会用 s[i] 越界访问、直接报错)
- 错误写法:空数组没特判就取 strs[0] → 正确写法:开头先判 strs 为空返回 ""(空数组时 strs[0] 会下标越界)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。