【19.最长公共前缀】

7 阅读1分钟

题目

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 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;
}

总结

算法:分治二分