LeetCode刷题笔记 14. 最长公共前缀
各种神仙算法,我暂时就不看了。
语法学习
C/C++库函数strstr和find实现子字符串查找
c++中的find函数,strstr,strcmp 的区别。
水平扫描
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty())return string();
string prefix=strs[0];
for(int i=1;i<strs.size();i++){
// 如果不是在前缀中找到第一个字符串,则将其从后截短 1 ,
// 注意如果条件只是单纯的找到,则可能第一个字符串可能出现在后续字符串的中部
while(strs[i].find(prefix)!=0){
prefix=prefix.substr(0,prefix.length()-1);
if(prefix.empty()) return "";
}
}
return prefix;
}
};
水平扫描优化(推荐)
想象数组的末尾有一个非常短的字符串,使用上述方法依旧会进行 S 次比较。优化这类情况的一种方法就是水平扫描。我们从前往后枚举字符串的每一列,先比较每个字符串相同列上的字符(即不同字符串相同下标的字符)然后再进行对下一列的比较。
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty())return string();
for(int i=0;i<strs[0].length();i++){
char c=strs[0][i];
for(int j=1;j<strs.size();j++){
if(i==strs[j].length()||strs[j][i]!=c)
return strs[0].substr(0,i);
}
}
return strs[0];
}
};
双指针
字符串加法学习一下。
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
//双指针法:指针i指向每串字符的同一个位置的字符,指针j用来遍历每个字符串
if(strs.empty())return string();
else if(strs.size()==1)return strs[0];
string result="";
//取第一个字符串为最长公共前缀,然后遍历每个字符串,来确定实际的最长公共前缀
for(int i=0;i<strs[0].size();++i)//i表示指向每个字符串的同一个位置的字符
{
for(int j=1;j<strs.size();++j)//j遍历到每个字符串
if(strs[0][i]!=strs[j][i])
return result;
result+=strs[0][i];
}
return result;
}
};
菜鸡解法(纯属个人记录)
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size()==0) return "";
if(strs.size()==1) return strs[0];
int num=strs.size(),len=strs[0].length(),max=0;
bool flag=false;
for(int j=0;j<len;j++){
if(flag) break;
for(int i=0;i<num;i++){
if(strs[0][j]!=strs[i][j]){
flag=true;
max--; //因为无论if判断有没有成立都要max++,如果提前中断的话要-1
break;
}
}
max++;
}
if(max==0) return "";
return strs[0].substr(0,max);
}
};
进阶 二分法(只为记录一个理解细节)
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, Math.min(low,high)); // 原文中为 (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;
}
}