题目链接:https://leetcode.com/problems/longest-common-prefix/
这是一个easy的题目,但是涉及的思维方式和方法还有一些用的比较少的高级数据结构都是值得讨论研究的,意味深长。LeetCode的前两百道题目各个都是经典,引人思考。这个题目要求一个字符串集合的最长公共前缀。
思路一:
一拿到题目的思路有两个,其中一个是Trie树,第二个就是这个实现起来相对快一些:最长公共前缀长度n一定小于等于最短字符串,然后逐个比较个字符串中第i个(i<=n)字符是否相同即可,于是有了如下代码:
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length==0 || strs==null)
return "";
StringBuilder sb=new StringBuilder();
int minLength=Integer.MAX_VALUE;
for(int i=0;i<strs.length;i++)
minLength=Math.min(minLength,strs[i].length());
for(int j=0;j<minLength;j++)
{
char c =strs[0].charAt(j);
int k=1;
for(;k<strs.length;k++)
if(c!=strs[k].charAt(j))
break;
if(k<strs.length)
break;
sb.append(c);
}
return sb.toString();
}
}
最坏时间复杂度为O(mn),空间复杂度为O(1),性能一般。
思路二:
先比较前两个字符串得到最长公共前缀,再用的到的最长公共前缀与后面的字符串一一比较,从而得到最终的最长公共前缀
代码很简单,但是我觉得Solutions里面的解法更优雅直接:
public String longestCommonPrefix1(String[] strs) {
if (strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++)
{
while (strs[i].indexOf(prefix) != 0)
{
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
}
return prefix;
}
思路三:
上述两两比较的方式(一趟复杂度为O(n))可以用归并的思想进行优化(一趟复杂度为logn),归并思想可以参考这两篇:https://blog.csdn.net/To_be_to_thought/article/details/83994248和https://blog.csdn.net/To_be_to_thought/article/details/83988767
代码如下:
public String longestCommonPrefix2(String[] strs) {
if (strs == null || strs.length == 0) return "";
return longestCommonPrefix(strs, 0 , strs.length - 1);
}
private String longestCommonPrefix(String[] strs, int l, int r) {
if (l == r) {
return strs[l];
}
else {
int mid = (l + r)/2;
String lcpLeft = longestCommonPrefix(strs, l , mid);
String lcpRight = longestCommonPrefix(strs, mid + 1,r);
return commonPrefix(lcpLeft, lcpRight);
}
}
String commonPrefix(String left,String right) {
int min = Math.min(left.length(), right.length());
for (int i = 0; i < min; i++) {
if ( left.charAt(i) != right.charAt(i) )
return left.substring(0, i);
}
return left.substring(0, min);
}
思路四:
前缀树这个思路是比较自然的思路,因为Trie树就是为这个而设计的数据结构。将字符串集合里的字符串建立在Trie树上,然后数从根节点到第一个分叉节点经历的边数。未完待续!!!