题目描述
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 " "。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解法
分治法
思路:我觉得比较好理解,简化为一个基本的模型也就是两两进行比较,得到的结果再利用迭代即可,类似二路归并?奈何迭代学的不太好,理解来说稍显困难。
贴下代码:
class soulution
{
public:
string longestCommonPrefix(vector<string>& strs)
{
if (!strs.size())
{
return "";
}
else
{
return longestCommonPrefix(strs, 0, strs.size() - 1);
//原来还可以这样重载
}
}
string longestCommonPrefix(const vector<string>& strs, int start, int end)
{
if (start == end)
{
return strs[start];//可以遍历到最小的那一棵树
}
else
{
int mid = (start + end) / 2;
string lcpLeft = longestCommonPrefix(strs, start, mid);
string lcpRight = longestCommonPrefix(strs, mid + 1, end);
return two_common(lcpLeft, lcpRight);
}
}
string two_common(const string& str1,const string& str2)
{
int minLength = min(str1.size(), str2.size());
int temp = 0;
for (int i = 0; i < minLength;i++)
{
if(str1[i]==str2[i])
temp++;
else break;//开始没加else出错了。。。
}
if(temp!=0)
{
string str3 = str1.substr(0, temp);
return str3;
}
else
return "";
}
};
我自己写的two_common函数稍显繁琐,可以简化来写,至于如何想出来的迭代实现,仍需多加思考。
二分查找法
这个解法用图片来展示是非常直观的:
贴下代码:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (!strs.size())
{
return "";
}
int low = 0;
string min = *min_element(strs.begin(), strs.end(), cmp);
//min_element函数返回指针或者迭代器,cmp是自定义比较函数,bool型
int high = min.size();
while (low < high)
{
int mid = (high - low + 1) / 2 + low;
if (isCommonPrefix(strs, mid))
low = mid;
else
high = mid - 1;
}
return strs[0].substr(0, low);
}
static bool cmp(const string &s, const string &t)
{
//key point:static
//静态成员只属于类,不属于对象
return s.size() < t.size();
}
bool isCommonPrefix(const vector<string>& strs, int length)
{
string str0 = strs[0].substr(0, length);
//处理0号字符串,裁剪为length长度的字符串
int count = strs.size();//字符串的个数
for (int i = 1; i < count; ++i)
{
string str = strs[i];
//外循环选择字符串
for (int j = 0; j < length; ++j)
{
//内循环遍历单个字符串的每个字符
if (str0[j] != str[j])
return false;
}
}
return true;
}
};
新学了很多东西,比如min_element()函数,静态成员等等,不过迭代还是好难quq
关于静态成员,不加static会报错,后来看到这篇文章,帮助很大:
reference to non-static member function must be called
思路要梳理一下再更新!
但是觉得这个写的也一般,若isCommonPrefix函数返回为真,之后再进行while循环更新mid的值,mid的值增大,在进行isCommonPrefix函数判断时一半的字符都被比较过了还要再比,感觉没必要,但怎么改进,没想出来,考虑改j的值让比较的字符位被指定。
超级简单的排序法
class Solution2 {
//先排序,再比较头尾,字典序
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty()) return string();
sort(strs.begin(), strs.end());
string st = strs.front(), en = strs.back();
int i, num = min(st.size(), en.size());
for(i = 0; i < num && st[i] == en[i]; i ++);
return string(st, 0, i);
}
};
代码简洁,字典序在这里解决问题很合适,运行快不快就看sort函数执行效率了。
字典序:
在计算机中,两个字符串比较大小,是按照从左到右的顺序进行比较,如果第1位相等,就比较第2位,直至有一位可以比较出大小来,则不再继续比较。
贴一个sort函数比较详细的链接:
C++ sort()排序函数