最长公共前缀

 

题目

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

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

示例 1:

输入: [“flower”,”flow”,”flight”] 输出: “fl”

示例 2:

输入: [“dog”,”racecar”,”car”] 输出: “” 解释: 输入不存在公共前缀。

说明:所有输入只包含小写字母 a-z 。

解法

1.逐个比较法

算法

  • 依次遍历字符串$[S_1,S_2,…,S_n]$
  • 寻找当前的公共前缀与字符串$S_i$的公共前缀prefix
  • 重复此过程直到遍历结束
  • 如果prefix为空,则返回空

代码

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++){
          //find 方法 通常达到linear in length()—pos乘以要匹配的序列的长度(最坏情况)。
            while(strs[i].find(prefix) != 0){
                prefix = prefix.substr(0,prefix.size()-1);
                if(prefix.empty()) return "";
            }
        }
        return prefix;
    }
};

复杂度分析

  • 时间复杂度:$O(S)$,S是所有字符串中字符数量的总和。 最坏的情况下,S个字符串都是相同的。算法会将字符串与其他字符串都进行一次比较。
  • 空间复杂度:$O(1)$,使用常数级别的额外空间。 ​

    2.水平扫描法

算法

  • 从前往后枚举字符串的每一列,先比较每个字符串相同列上的字符(即不同字符串相同下标的字符),再对下一列进行比较
  • 停止条件:某个字符串已经遍历完 i==strs[j].size(); 或者遇到不相等字符 strs[j][i] != ch;

代码

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

复杂度分析

  • 时间复杂度:$O(S)$,S是所有字符串中字符数量的总和。

最坏情况:输入数据为 $n$ 个长度为 $m$ 的相同字符串,算法会进行 $S=m \cdot n$ 次比较

最好情况:只需进行$n \cdot minLen$次比较,其中$ minLen $是数组中最短字符串的长度

  • 空间复杂度:$O(1)$,使用常数级别的额外空间。