归并的解法
题目:编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,”flow”,”flight”]
输出: “fl”
示例 2:
输入: [“dog”,”racecar”,”car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
在网上看到好多人的做法其实还是暴力解法,这个题可以用归并的方法来解决,归并的一般用途是排序,即归并排序,在这里用来解这道题是最合适不过了,主要思想就是,先划分,再归并,这样首先求出2个字符串元素的最长公共前缀,然后再求出4个元素的最长公共前缀,以此类推。但是每一次归并仅仅还是针对两个已经求出的最长公共前缀来做归并的,避免了对整个字符串元素进行遍历,而且最长公共元素是越来越短,时间效率上也就是越来越快,那么下面附上代码供大家参考:
class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
return mergeCommonPrefix(strs, 0, strs.length - 1);
}
public String merge(String s1, String s2) {
if (s1 == null || s2 == null || s1 == "" || s2 == "") return "";
StringBuffer sb = new StringBuffer();
int i = 0;
int index = Math.min(s1.length() - 1, s2.length() - 1);
while (i <= index) {
if (s1.charAt(i) == s2.charAt(i)) sb.append(s1.charAt(i++));
else return sb.toString();
}
return sb.toString();
}
public String mergeCommonPrefix(String[] a, int start, int end) {
if (start < end) {
int mid = (start + end) / 2;// 划分子序列
String s1 = mergeCommonPrefix(a, start, mid);// 对左侧子序列进行递归合并
String s2 = mergeCommonPrefix(a, mid + 1, end);// 对右侧子序列进行递归合并
return merge(s1, s2);// 合并两个最长公共前缀
} else {// 当子序列中只有一个元素时结束递归
return a[start];
}
}
}
虽然看起来我的代码很长,但是核心代码就是那个merge()函数,是不是很短。归并的时间复杂度:O(n log n),但是我认为要比这个复杂度还要低,因为最长公共前缀一定是在不断缩短或不变。