解法一: 横向扫描(暴力匹配)
可以使用第一个字符串与第二个字符串进行最长公共子串的匹配,再用这个最长公共子串和后面的字符串进行匹配,如果匹配到的子串为空,则最长公共子串一定为空。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) {
return "";
}
String prefix = strs[0];
for(int i = 1; i < strs.length; i++){
prefix = longestCommonPrefix(prefix, strs[i]);
if(prefix.length() == 0)break;
}
return prefix;
}
public String longestCommonPrefix(String prefix, String str){
int index = 0;
int length = Math.min(prefix.length(), str.length());
while(index < length && prefix.charAt(index) == str.charAt(index)){
index++;
}
return prefix.substring(0,index);
}
}
解法二 分治
主要思想:把字符串数组分为左右两个子问题,分别进行求解,再求两个子问题解的最长前缀。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) return "";
return longestCommonPrefix(strs,0,strs.length-1);
}
public String longestCommonPrefix(String[] strs, int start, int end){
if(start == end){//如果分解到只剩一个字符串则返回这个字符串
return strs[start];
}else{
int mid = (end - start)/2 +start;
String leftLCP = longestCommonPrefix(strs,start, mid);
String rightLCP = longestCommonPrefix(strs,mid + 1, end);
return commonPrefix(leftLCP, rightLCP);
}
}
public String commonPrefix(String l, String r){
int index = 0;
int len = Math.min(l.length(), r.length());
while(index < len && l.charAt(index) == r .charAt(index)){
index++;
}
return l.substring(0,index);
}
}
解法三 二分查找法
字符串数组的最大前缀由字符串数组中的最短字符串决定因此
- 先计算最短字符串的长度
- 对字符数组第一个字符串进行二分查找
如果前半部分属于最长前缀则丢弃前半部分,继续查找后半部分
如果前半部分不属于前缀,则丢弃后半部分,继续查找前半部分
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) return "";
int minLen = strs[0].length();//最短字符串的长度
for(String each : strs){
minLen = each.length() < minLen ? each.length() : minLen;
}
int low = 0, high = minLen;
while(low <= high){
int mid = (low + high)/2;
if(isCommonPrefix(strs,mid)){
low = mid + 1;
}else{
high = mid -1;
}
}
return strs[0].substring(0,(low + high)/2);
}
public boolean isCommonPrefix(String[] strs, int mid){
String subStr = strs[0].substring(0,mid);
for(int i = 0; i < strs.length; i++){
for(int j = 0; j < subStr.length(); j++){
if(strs[i].charAt(j) != subStr.charAt(j))return false;
}
}
return true;
}
}
解法四 纵向扫描
- 字符串数组左对齐按行排列
- 按列纵向进行遍历判断下一个字符串第i列的字符是否等于第一行第i列的字符
如果不相等则返回子串
如果i等于当前行的长度则返回子串
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) return "";
int length = strs[0].length();
int count = strs.length;
for(int i = 0; i < length; i++){
char c = strs[0].charAt(i);
for(int j = 1; j < count; j++){
if(strs[j].charAt(i)!=c || strs[j].length() == i){
return strs[0].substring(0,i);
}
}
}
return strs[0];
}
}
参考
https://leetcode-cn.com/problems/longest-common-prefix/solution/zui-chang-gong-gong-qian-zhui-by-leetcode-solution/