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;
}
};
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/