Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串
""。
此题要求的是字符串数组中所有字符串的最长公共前缀,既然是最长公共前缀,那么它的长度肯定受到数组中最短的子串的限制,公共前缀最长一定不会超过它,所以我们可以先将数组中的字符串按照长度进行一个排序,比如:
["flower","flow","flight"]
我们先对其按长度进行排序:
["flow""flower","flight"]
然后以数组中的第一个字符串flow为基准进行匹配,分别遍历字符串上的每一个字符,查询后续的字符串中的对应位置上是否也有相同的字符,若有,则加入结果,若没有,则结束匹配。
对于一些特殊情况,比如数组中只有一个字符串:["a"],我们只需直接返回这个字符串即可。
而如果数组中出现了空字符串,那么一定不存在公共前缀,直接返回空字符串即可。
代码如下:
public static String longestCommonPrefix(String[] strs) {
// 数组中仅有一个字符串,直接返回
if (strs.length == 1) {
return strs[0];
}
StringBuilder sb = new StringBuilder();
List<String> list = new ArrayList<>();
for (String str : strs) {
if (str.equals("")) {
// 若是数组中有空字符串,直接返回
return sb.toString();
} else {
list.add(str);
}
}
// 将集合按照字符串长度排序
list.sort(Comparator.comparingInt(String::length));
// 以集合的第一个元素为基准匹配
for (int i = 0; i < list.get(0).length(); i++) {
// 取出i位置字符
char c = list.get(0).charAt(i);
int j;
// 遍历后续的字符串
for (j = 1; j < list.size(); ++j) {
if (list.get(j).charAt(i) != c) {
// 若有不匹配,直接返回
return sb.toString();
}
}
// 将字符c加入sb
sb.append(c);
}
return sb.toString();
}
当然了,我们可以用更优雅的方式来处理它,就是对每个字符串两两匹配,求得最长公共前缀,例如:["flower","flow","flight"],首先求得flower和flow的最长公共前缀,结果为flow,然后以flow和flight匹配求得最长公共前缀,结果为fl。
代码如下:
public static String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
// 以数组中的第一个元素为基准
String prefix = strs[0];
for (int i = 1; i < strs.length; i++) {
// 两两匹配,得到最长公共前缀
prefix = getPrefix(prefix, strs[i]);
if (prefix.length() == 0) {
// 若prefix为0,说明数组中有空字符串,结束循环
break;
}
}
return prefix;
}
public static String getPrefix(String str1, String str2) {
// 求得最短的字符串长度
int len = Math.min(str1.length(), str2.length());
int index = 0;
while (index < len) {
if (str1.charAt(index) == str2.charAt(index)) {
// 若匹配,index++
++index;
}else {
// 若不匹配,结束循环
break;
}
}
// 截取最长公共前缀
return str1.substring(0, index);
}
此题得解。