Write a function to find the longest common prefix string amongst an array of strings.
Method1:横向比较
class Solution {
public:
//indexof返回某个字符串首次在string出现的位置
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty()) return "";
string prefix = strs[0];
size_t found;
for(int i=1;i<strs.size();i++){
found=strs[i].find(prefix);
while(found==0){
//如果之前的最长前缀在这个字符串没有出现在首位的话,就将前缀减掉一个,再继续进入while循环判断
prefix=strs[i].substr(0,prefix.length()-1);
if(prefix.compare("")) return "";
}
}
return prefix;
}
};
最直接的方法,结果Submission Result: time limited exceed
Method2:纵向比较
class Solution {
public:
//indexof返回某个字符串首次在string出现的位置
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty()) return "";
string s=strs[0];
for(int i=0;i<s.length();i++){
char c=s[i];
for(int j=1;j<strs.size();j++){
if(i==strs[j].length()||strs[j][i]!=c){
//当i为str[j]的长度时就已经读到了第i+1个字符串了
//很简单的理解为,读完了或者是出现不相等的情况就把结果返回了
//所有字符串公共的字符串只要有一个不相等就结束了
return s.substr(0,i);
}
}
}
return s;
}
};
自己写的时候在返回值的地方出了问题,string.substr(i,j)返回的结果是string[i]开始长度为j的子字符串,也就是到i+j-1
Method3:分治算法(divide and conquer)
https://blog.csdn.net/songzitea/article/details/52262537
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size()==0) return "";
else{
return longestPrefix(strs,0,strs.size()-1);
}
}
string longestPrefix(vector<string>& strs,int start,int end){
if(start==end) return strs[start];
int mid=(start+end)/2;
string left=longestPrefix(strs,start,mid);
string right=longestPrefix(strs,mid+1,end);
return commonPrefix(left,right);
}
string commonPrefix(string left,string right){
int ll=left.length();
int rl=right.length();
int length=min(ll,rl);
for(int i=0;i<length;i++){
if(left[i]!=right[i]) return left.substr(0,i);
}
return left.substr(0,length);
}
};
需要找很多字符串的公共前缀,那么就分开,一点一点的找,最典型的就是二分查找
还有就是递归的最小的范围的那个函数要仔细写啊,尤其是用函数求子字符串的时候把细节搞清楚啊
Method4:二分查找
上一个是将所有的字符串一半一半通过递归的方法进行比较。这次是将长度最短的字符一半一半的拆开进行比较,前一半匹配成功了就再比较下一半,没有成功的话就将这一段减半再进行比较。
这个代码看了很久,就是运行通不过,卡在{‘a’,‘b'}和{‘a’}上了
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size()==0) return "";
int minlength;
for(int i=0;i<strs.size();i++){
minlength=min((int)strs[i].length(),minlength);
}
int low=1;
int high=minlength;
int middle;
while(low<=high){
middle=(low+high)/2;
if(isCommonPrefix(strs,middle))
low=middle+1;
else high=middle-1;
}
return strs[0].substr(0,(low+high)/2);
}
bool isCommonPrefix(vector<string>& strs,int end){
string s=strs[0].substr(0,end);
for(int i=1;i<strs.size();i++){
if((int)(strs[i].find(s))!=0){
return false;}
}
return true;
}
};
接下来是solution里面的Java的做法,提交上去运行没有错误,c++的已经改到几乎完全相同了,但是就是不知道问题在哪,很有可能是调用的函数的区别,解题的思路就是这样了。
class Solution{
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0)
return "";
int minLen = Integer.MAX_VALUE;
for (String str : strs)
minLen = Math.min(minLen, str.length());
int low = 1;
int high = minLen;
while (low <= high) {
int middle = (low + high) / 2;
if (isCommonPrefix(strs, middle))
low = middle + 1;
else
high = middle - 1;
}
return strs[0].substring(0, (low + high) / 2);
}
private boolean isCommonPrefix(String[] strs, int len){
String str1 = strs[0].substring(0,len);
for (int i = 1; i < strs.length; i++)
if (!strs[i].startsWith(str1))
return false;
return true;
}
Method5:与树相关的算法。
https://leetcode.com/problems/longest-common-prefix/solution/