题目描述:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z
。
算法
为了运用这种思想,算法要依次遍历字符串 [S_1 \ldots S_n][S1…Sn],当遍历到第 ii 个字符串的时候,找到最长公共前缀 LCP(S_1 \ldots S_i)LCP(S1…Si)。当 LCP(S_1 \ldots S_i)LCP(S1…Si) 是一个空串的时候,算法就结束了。 否则,在执行了 nn 次遍历之后,算法就会返回最终答案 LCP(S_1 \ldots S_n)LCP(S1…Sn)。
图 1. 查找最长公共前缀 (水平扫描法)
自己写的代码:
/**
* 最长公共前缀
*
* @author 86176
*
*/
public class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0 || strs[0].equals("")) // 字符串数组为0或者第一个数组为空,则返回空
{
return "";
}
String temp = strs[0];
for (int i = 1; i < strs.length; i++) // 遍历其他字符串进行比较
{
if (strs[i].length() == 0) // 有一个为空,那么就没有最长公共前端
{
return "";
} else if (strs[i].length() < temp.length()) // 当字符串长度比temp要短的情况
{
for (int j = 0; j < strs[i].length(); j++) {
if (temp.charAt(j) != strs[i].charAt(j)) // 当遇到不相同的情况
{
temp = strs[i].substring(0, j); // 用substring()可以将0到j的值值给temp,j位置的值不会被包括进去
break;
}
if (j == strs[i].length() - 1) // 如果都遍历完其中一个字符串还没结束,那么这个最短字符串就是
{
temp = strs[i];
}
}
} else {
for (int j = 0; j < temp.length(); j++) // 当temp的长度最短时
{
if (temp.charAt(j) != strs[i].charAt(j)) {
temp = strs[i].substring(0, j);
break;
}
}
}
}
return temp;
}
public static void main(String[] args) {
String[] strs = { "abcfdsg", "abcrrr", "abcd", "abcde", "abcdef", "abcdefg" };
String s = new Solution().longestCommonPrefix(strs);
System.out.println(s);
}
}
输出:
abc
官方答案:利用了字符串的indexOf方法,通过返回位置是不是0判断是不是公共前缀,如果返回值不是0,就将这个临时公共前缀删除最后一个字符,在进行尝试,直到返回值为0为止,代码如下:
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++)
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
return prefix;
}
复杂度分析
-
时间复杂度:O(S)O(S),S 是所有字符串中字符数量的总和。
最坏的情况下, nn 个字符串都是相同的。 算法会将 S1S1 与其他字符串 [S_2 \ldots S_n][S2…Sn]都做一次比较。这样就会进行 SS 次字符比较,其中 SS 是输入数据中所有字符数量。
-
空间复杂度:O(1)O(1), 我们只需要使用常数级别的额外空间。