分析
这道题其实非常简单。 按照常规思维来看,我们只需要对字符串进行纵向扫描, 分别对比字符串的每个字母,当字母不一样时停止扫描并返回当前存储的结果。
但是,这道题的思路可以进一步拓展。
首先,假设字符串成员为 strs = ['leet', 'leetcode', 'lee', 'le']
。
我们可以对字符串进行分治。即分别对 strs = ['leet', 'leetcode']
和 strs = ['lee', 'le']
进行分治。
求出 strs = ['leet', 'leetcode']
的最长公共前缀为 leet
,
strs = ['lee', 'le']
的最长公共前缀为 le
。
随后,我们对这两个字符串进行比较,得到 leet
与 le
的最长公共前缀为 le
。
当然,此题还可以利用二分查找的思路进行解答。
显然,最长公共前缀小于等于最短字符串的长度,
所以我们先找出最短字符串的长度 min_len
。
然后,我们取字符串中间值 mid
,
先比较每个字符串的前 mid
个字符,若都相同则以 mid+1
为起点比较后 len - (mid + 1)
个字符。
从而将搜索范围缩小,得出答案。
解答
class Solution {
public:
string longestCommonPrefix(vector<string> &strs) {
if (!strs.size())
return "";
auto min_len = min_element(strs.begin(), strs.end(),
[](const string &s, const string &t) {
return s.size() < t.size();
})
->size();
auto low = 0;
auto high = min_len;
while (low < high) {
auto mid = (high - low + 1) / 2 + low;
if (isCommonPrefix(strs, mid))
low = mid;
else
high = mid - 1;
}
return strs[0].substr(0, low);
}
bool isCommonPrefix(const vector<string> &strs, int len) {
auto str0 = strs[0].substr(0, len);
auto cnt = strs.size();
for (auto i = 0; i < cnt; ++i) {
auto str = strs[i];
for (auto j = 0; j < len; ++j)
if (str[j] != str0[j])
return false;
}
return true;
}
};