【题目描述】
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
【测试用例】
示例1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
【思路分析】
我的思路很简单,应该也是很多人第一时间会想到的思路:纵向比对。
以字符串数组的第一个字符串为基准,用基准字符串的第一个字符与其余所有字符串的第一个字符依次比对,如果均比对成功,则比较第二个字符,依此类推....如果出现未比对成功的,则直接结束比对,此时的最长公共前缀就是基准字符串的0号位置到当前比对字符的前一个位置。
【参考代码】
C语言实现
这里有一点要注意,函数中用于保存结果的char型指针一定要动态分配内存,不能用prefix[200]的方式赋值,因为这样赋值是局部变量,它的作用域只在函数内,函数返回不会将其值返回到主函数。我最开始就是用的这个方法,排了很久bug,还是代码量太少,这应该是一个很基本的编程常识。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//easy-14-最长公共前缀
char* longestCommonPrefix(char** strs, int strsSize);
int main(){
int i;
int strsSize = 3;
char** strs = (char**)malloc(sizeof(char*)*strsSize);
for(i=0;i<strsSize;i++){
strs[i] = (char*)malloc(sizeof(char)*200);
scanf("%s",strs[i]);
}
char* res = longestCommonPrefix(strs, strsSize);
printf("%s", res);
return 0;
}
char* longestCommonPrefix(char** strs, int strsSize) {
int i, j, k=0;
char* prefix = (char*)malloc(sizeof(char)*strlen(strs[0]));
int flag=0;
for (i=0;i<strlen(strs[0]);i++){
for(j=1;j<strsSize;j++){
if(strs[0][i]!=strs[j][i]){
flag=1;
break;
}
}
if(flag){
break;
}
prefix[k++] = strs[0][i];
}
if(k==0){
prefix[0] = '\0';
}else{
prefix[k]='\0';
}
return prefix;
}
C++实现
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//easy-14-最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs);
};
string Solution::longestCommonPrefix(vector<string>& strs){
string res("");
int i,j,flag=0,k=0;
for(i=0;i<strs[0].size();i++){
for(j=1;j<strs.size();j++){
if(strs[0][i] != strs[j][i]){
flag=1;
break;
}
}
if(flag){
break;
}
k++;
res = strs[0].substr(0,k);
}
return res;
}
int main(){
int i, nums;
vector<string> strs;
Solution sol;
cout<<"请输入字符串个数:";
cin>>nums;
string input;
for(i=0;i<nums;i++){
cin>>input;
strs.push_back(input);
}
string res = sol.longestCommonPrefix(strs);
cout<<res<<endl;
return 0;
}
【题解思路】
说实话,题解思路真是让我五体投地,膜拜大佬。使用字符串字典序的方法,具体如下:
简单来说就是找出所有字符串中字典序的最大和最小,只需求得最大和最小字符串的最长公共前缀,这个最长公共前缀即为所有字符串的最长公共前缀。
(Ps:字典序就是按照字母在字母表中的顺序来进行比较,不是比较的字符串长度。比如字母表中a在b前面,所以a>b,再比如abc>abd)
那么为什么找到字典序的最大字符串和最小字符串的最长公共前缀就可以确定所有串的最长公共前缀呢?
举个例子:假设有两个最小和最大字符串,分别是"abcd"和"abcde",那么所有以abcda、abcdb、abcdc、abcdd开头的字符串都位于这两个字符串之间(不管该字符串有多长),而这些字符串都一定有abcd这个前缀,因为但凡不具备这个前缀,那这个字符串就一定不会在"abcd"和"abcde"之间,换句话说,这时最大和最小字符串或许就不是这两个了。
这种方法第一次见到这道题应该几乎不会有人想到(大佬除外),但是见到了学到就是自己的。
【参考代码】
使用STL的minmax_element函数来求得最大和最小字符串。p.first返回的是指向最小的字符串的指针,p.second返回指向最大的字符串的指针。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
//easy-14-最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs);
};
string Solution::longestCommonPrefix(vector<string>& strs){
auto p = minmax_element(strs.begin(),strs.end());
for(int i=0; i<p.first->size();++i){
if(p.first->at(i) != p.second->at(i)){
return p.first->substr(0,i);
}
}
}
int main(){
int i, nums;
vector<string> strs;
Solution sol;
cout<<"请输入字符串个数:";
cin>>nums;
string input;
for(i=0;i<nums;i++){
cin>>input;
strs.push_back(input);
}
string res = sol.longestCommonPrefix(strs);
cout<<res<<endl;
return 0;
}