14.最长前缀子串Longest Common Prefix
定义
首先定义Longest Common Prefix(引用自Discuss@Vgn):
It seems that it is not to check between pair of strings but on all the strings in the array.
For example:
{“a”,“a”,“b”} should give “” as there is nothing common in all the 3 strings.
{“a”, “a”} should give “a” as a is longest common prefix in all the strings.
{“abca”, “abc”} as abc
{“ac”, “ac”, “a”, “a”} as a.
算法思想
- 取第一个字符串的第一个字符和后面的字符串的第一个对比,如果有一个不相同,或者字符串结束则返回
- 如果都相同,则向LCP中添加第一个字符
- 取第一个字符串的第二个字符…循环直到结束。
如果说上面这种是垂直扫描的思想,Solution中提到了另一种水平扫描的思想,先两两比较字符串的LCP,然后再和后面的字符串依次对比。
以上两种方法时间复杂度都是O(S),空间复杂度O(1)。 其中S=m*n,n是string的个数,m是string的长度。
第三种想法是分治的思想,但是时间复杂度O(S), 需要O(m*log(n))的额外空间。
第四种想法是二分查找的思想,但是时间复杂度需要O(S*log(n)),空间O(1)。
关于分治和二分的时间复杂度,看到了一篇文章说的很好,http://blog.csdn.net/qilei2010/article/details/51345278
大意就是说二分法的复杂度一般是O(logN),分治算法是O(N),这是因为二分法每次丢弃不符合条件的一半,而分治算法只是将一个问题分成几个小问题,并没有降低问题的规模。
我的代码
string longestCommonPrefix(vector<string>& strs) {
string lcp="";
if (strs.size()!=0&&strs[0]!="")
{
string s=strs[0];
for (int j=0;j<s.length();j++)
{
char pre=strs[0][j];
for(int i=1;i<strs.size();i++)
{
if (pre!=strs[i][j])
{
return lcp;
}
}
lcp+=pre;
}
}
return lcp;
}
注意判断输入为空和第一个字符串是空的情况。
看了网友的一些评论,发现了如下几个问题:
第一行处理异常情况,先返回
有网友指出lcp+=pre会多产生一个string,所以改用了index和substr
注意index++的时候要判断i是否遍历完了vector中所有的string
删除了一些不必要的定义比如s,pre
if(strs.size()==0||strs[0]=="") return ""; int index=0; for (int j=0;j<strs[0].length();j++) { int i=1; for(;i<strs.size()&&strs[i].size()>j;i++) { if (strs[0][j]!=strs[i][j]) { return strs[0].substr(0,index); } } if(i==strs.size())index++; } return strs[0].substr(0,index);
看着好像简洁多了XD,但是没有什么卵用,依然是9ms。