LeetCode 14. 最长公共前缀

136 阅读2分钟

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"],首先求得flowerflow的最长公共前缀,结果为flow,然后以flowflight匹配求得最长公共前缀,结果为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);
}

此题得解。