题目描述
本文是LC第14题,最长公共前缀,题目描述如下:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
限制
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
解释:输入不存在公共前缀。
解题思路
字符串前缀:前缀是指字符串的任意首部。比如字符串“abbc”的前缀有“a”,“ab”,“abb”,“abbc”。同样,字符串的任意尾部是字符串的后缀,“abbc”的后缀有“c”,“bc”,“bbc”,“abbc”
- 暴力思路:将字符串数组转换为二维字符数组思考,如下图所示,先比较每个字符串的第一个元素是否相等,然后比较第二个元素,直到遇到第n位元素中出现了不相等的情况,记录下当前的公共前缀,退出循环。
写出的代码如下
class Solution {
public:
/* 暴力解法
* 以strs[0]为基准字符串,将str[0][0](第一个字符)依次与str[1]、str[2]...中的第一个字符进行比较。
* 再将str[0][1](第二个字符)依次与其他字符串比较
* ......
* 直到某个字符与基准字符串中的字符不相等时退出
* 两点bug:(strs为空怎么办? strs[0])
* (1). 输入的vector为空 --- 判空语句
* (2). 输入的vector中只有一个字符串且为空串 --- 逻辑本身没有问题,但是要注意 不相等退出比较循环后 k值不加*(最终返回string(strs[0].begin(), strs[0].begin()+k)为 左闭右开),即k值+1的条件是 flag为false
*/
string longestCommonPrefix(vector<string>& strs) {
if(!strs.size()) return ""; // 空数组返回""
bool flag = false; // 记录是否相等,若不想等则==true
int k = 0; // k 遍历字符串元素
while(strs[0][k] && !flag){
char cmp = strs[0][k];
for(int i = 0; i < strs.size(); ++i){
if(strs[i][k] - cmp){
flag = true;
break;
}
}
if(!flag) ++k;
}
return string(strs[0].begin(), strs[0].begin()+k);
}
};
解释:
while(strs[0][k] && !flag)
描述了一个外层循环:若二维字符数组的第0行第K个元素为空,退出循环。为什么只是第0行?这里我们只以第0行的字符串为基准字符串,其他的1~n-1行的字符串依次与基准字符串逐字符比较。
若strs[0][k] 非空,但 flag == true,则退出循环,说明遇到了不想等的,此时已找到最长公共前缀。
for(int i = 0; i < strs.size(); ++i)
描述了一个内层循环,结合外层循环,内层循环的意思就是依次访问 strs 第 k 列的所有字符,如果某个字符与第一个字符串第k列的字符不想等,置flag为true,退出循环,那么 strs[0][0] ~ strs[0][k-1]组成的子字符串就是要找的最长公共前缀。
- 另一种代码
此种解法利用了C++对字符的一些处理函数,比较起来比较方便,但不是笔者推荐的一种。感兴趣可以参考下如下的实现,思路基本和暴力解法一致。
class Solution {
public:
/*
* 初始值以 strs[0]为基准字符串 prefix
* 将prefix与每个string进行比较,找到prefix与待比较string中的最长公共前缀,更新prefix为最长公共前缀
* 循环直到遍历所有string
* 找到prefix与待比较string中的最长公共前缀:
* 判断prefix是否是prefix与string的最长公共前缀
* 若不是,将prefix最后一位截断(若prefix为"",则直接return ""),继续比较
* 若是,退出循环
* bug: strs为空,需要加判空条件
*/
string longestCommonPrefix(vector<string>& strs) {
if(!strs.size()) return "";
string prefix = strs[0];
for(string k : strs){
while(k.find(prefix)){
if(!prefix.size()) return "";
prefix = string(prefix.begin(), prefix.end()-1);
}
}
return prefix;
}
};