0%

14.最长公共前缀

纵向扫描

最长公共前缀的含义,就是所有字符串在前若干个位置上的字符都相同,因此可以按列来检查。

先求出所有字符串中的最短长度,因为公共前缀长度不可能超过它。随后从第 $0$ 列开始依次判断,取第一个字符串当前位置的字符作为基准,再和其余字符串同一位置的字符比较。如果某一列出现不同字符,说明公共前缀到此为止;否则就把该字符加入答案。

时间复杂度 $O(nm)$

空间复杂度 $O(1)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public String longestCommonPrefix(String[] strs) {
int minLen = Integer.MAX_VALUE;
for (String s : strs) {
minLen = Math.min(minLen, s.length());
}
int n = strs.length;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < minLen; ++i) {
char cur = strs[0].charAt(i);
boolean flag = true;
for (int j = 1; j < n; ++j) {
if (strs[j].charAt(i) != cur) {
flag = false;
}
}
if (!flag) {
break;
}
sb.append(cur);
}
return sb.toString();
}
}

以第一个字符串为基准

也可以直接把第一个字符串当作候选答案。

遍历第一个字符串的每一个位置,检查其余所有字符串在该位置是否也存在且字符相同。只要某个字符串已经到头,或者当前位置字符不同,就说明公共前缀只能到当前位置之前,直接返回第一个字符串的前缀即可。

这种写法本质上也是纵向扫描,只是省去了额外统计最短长度的过程。

时间复杂度 $O(nm)$

空间复杂度 $O(1)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public String longestCommonPrefix(String[] strs) {
int n = strs.length;
String first = strs[0];
for (int i = 0; i < first.length(); ++i) {
char cur = first.charAt(i);
for (String s : strs) {
if (i == s.length() || s.charAt(i) != cur) {
return first.substring(0, i);
}
}
}
return first;
}
}