LeetCode 腾讯精选练习50 题——14. 最长公共前缀

题目

LeetCode 腾讯精选练习50 题——14. 最长公共前缀

解答

1. 方法一

第一个字符串和第二个匹配得出一个公共前缀后,再用这个前缀与下一个字符串匹配,重复下去到最后一个,代码如下:

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if(strs.size() == 0)
            return "";
        string prefix  = strs[0];
        for(int i = 1; i < strs.size(); i++) {
            int j = 0;
            for(; j < min(prefix.length(), strs[i].length()); j++)
                if(strs[i][j] != prefix[j])
                    break;
            prefix = prefix.substr(0,j);
        }
        return prefix;
    }
};

2. 方法二(分治法)

答案思路:首先找到所有字符串中最短的一个,然后再对这个字符串进行二分:先使用左边部分去遍历全部字符串,如果这个部分是公共前缀,则去使用右边部分去遍历全部字符串;如果不是公共前缀,则继续将左边部分的字符串划分为两等份,重复上面的操作。

PS:这个方法不仅实现起来麻烦,时间复杂度还比方法一大,我当时实现答案这个思路是因为我懒得去分析,直接默认答案越后面的方法的用时越少了......

代码如下:

【注意】注意判断某字符串是否为最长公共前缀的函数isPrefix的输入参数中,min是字符串数组中最短的字符串所在下标,length则是(截取字符串部分的长度 - 1)即每次检查的是strs[min][0] ~ strs[min][length]是否为最长公共前缀。之所以在longestCommonPrefix中的返回是(low+high)/2 + 1而不是mid,是因为能跳出while循环到达返回这里有两种情况:

1)low = mid+1执行完后,low > high,这时候,low比high大1,且0-mid+1才是最长公共前缀

2)high = mid-1执行完后,low>high,这时候,low比high大1,且0-mid是最长公共前缀,这个时候,high所在位置就是mid,且 (low+high) / 2等于mid

其中值得提醒一点的是,要在while的判断语句中出现low>high这种情况,在前一次的循环必定会有low == high,那么low比high大的时候,也只是大1而已。因为low(high)的每次更新都是取二者的中值加一(减一),这就导致了在low不等于high的情况,在一次更新中就能达到low最多只能增加到high,或者high最多可以减少到low。

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if(strs.size() == 0)
            return "";
        int min_val = INT_MAX, min = 0;
        for(int i = 0; i < strs.size(); i++)
            if(strs[i].length() < min_val) {
                min_val = strs[i].length();
                min = i;
            }
        int low = 0, high = strs[min].length()-1, mid = 0;
        while(high >= low) {
            mid = (low+high) / 2;
            if(isPrefix(strs, min, mid))
                low = mid + 1;
            else
                high = mid - 1;
        }
        if(high < 0)
            return "";
        return strs[min].substr(0,(low+high)/2 + 1);
    }
private:
    bool isPrefix(vector<string>& strs, int min, int length) {
        for(int i = 0; i < strs.size(); i++) {
            for(int j = 0; j <= length; j++) {
                if(strs[i][j] != strs[min][j])
                    return false;
            }
        }
        return true;
    }
};