题目
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入: strs = ["flower","flow","flight"]
输出: "fl"
题解
方式一:纵向扫描
从第一个字符串中不断截取前缀,直到不符合条件
复杂度:不会算
public String longestCommonPrefix(String[] strs) {
if (strs.length == 1) return strs[0];
String first = strs[0];
String ans = "";
for (int i = 1; i <= first.length(); i++) {
String prefix = first.substring(0, i);
for (String str: strs) {
if (!str.startsWith(prefix)) {
return ans;
}
}
ans = prefix;
}
return ans;
}
方式二:横向扫描
遍历字符串,取当前公共前缀和当前字符串的公共前缀。
复杂度:不会算
public String longestCommonPrefix(String[] strs) {
if (strs.length == 1) return strs[0];
String prefix = strs[0];
for (int i = 1; i < strs.length; i++) {
int len = Math.min(prefix.length(), strs[i].length());
int index = 0;
while (index < len && prefix.charAt(index) == strs[i].charAt(index)) {
index++;
}
prefix = prefix.substring(0, index);
if (prefix.length() == 0) {
break;
}
}
return prefix;
}
方式三:分治
复杂度:不会算
public String longestCommonPrefix(String[] strs) {
if (strs.length == 1) return strs[0];
// 分治思想:大事化小
return longestCommonPrefix(strs, 0, strs.length - 1);
}
public String longestCommonPrefix(String[] strs, int start, int end) {
if (start == end) {
return strs[start];
}
int mid = start + (end - start) / 2;
String left = longestCommonPrefix(strs, start, mid);
String right = longestCommonPrefix(strs, mid + 1, end);
// 到这里类似横向扫描,找两个字符串的公共前缀
int minLen = Math.min(left.length(), right.length());
for (int i = 0; i < minLen; i++) {
if (left.charAt(i) != right.charAt(i)) {
return left.substring(0, i);
}
}
return left.substring(0, minLen);
}
方式四:二分
公共前缀范围是【0,minLen】,二分找符合条件的长度
public String longestCommonPrefix(String[] strs) {
if (strs.length == 1) return strs[0];
int minLen = Integer.MAX_VALUE;
for (String str: strs) {
minLen = Math.min(str.length(), minLen);
}
int low = 0;
int high = minLen;
while (low < high) {
int mid = low + (high - low + 1) / 2; // +1防止死循环
if (isCommonPrefix(strs, mid)) {
low = mid;
} else {
high = mid - 1;
}
}
return strs[0].substring(0, low);
}
public boolean isCommonPrefix(String[] strs, int len) {
String prefix = strs[0].substring(0, len);
for (int i = 1; i < strs.length; i++) {
if (!strs[i].startsWith(prefix)) {
return false;
}
}
return true;
}
总结
算法:分治
、二分