link: https://leetcode.com/problems/longest-common-prefix/
Solution 1: 横向比较
追踪最长前缀的长度,并依次进行比较
class Solution {
public String longestCommonPrefix(String[] strs) {
int len = strs.length;
if(len == 0) return "";
if(strs[0].length() == 0) return "";
int max = strs[0].length();
for(int i=1; i<len; i++) {
int p = 0;
if(strs[i].length() == 0) return "";
int minLen = Math.min(strs[i].length(), strs[i-1].length());
while(p < minLen) {
if(strs[i].charAt(p) == strs[i-1].charAt(p)) {
p++;
} else {
break;
}
}
max = Math.min(max, p);
}
return strs[0].substring(0, max);
}
}
TC: O(n), n是所有string长度的和
SC: O(1)
缺点:当一个非常短的string在数组的末尾时,该方法会非常耗时
Solution 2: 纵向比较
按位比较每一个string
class Solution {
public String longestCommonPrefix(String[] strs) {
int len = strs.length;
if(len == 0) return "";
if(len == 1) return strs[0];
if(strs[0].length() == 0) return "";
for(int i=0; i<strs[0].length(); i++) {
char c = strs[0].charAt(i);
for(int j=1; j<len; j++) {
if(i >= strs[j].length()) {
return strs[j];
}
if(strs[j].charAt(i) != c) {
return strs[0].substring(0, i);
}
}
}
return strs[0];
}
}
TC:O(n),worst case:n等于所有字符串字符数的和,average的复杂度为len * minStringLen。
SC: O(1)
Note: 要注意纵向比较时字符串长度溢出
Solution 3:Divide and Conquer
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length == 0) return "";
return findLCP(strs, 0, strs.length-1);
}
public String findLCP(String[] strs, int l, int r) {
if(l == r) return strs[l];
int mid = (l + r) / 2;
String left = findLCP(strs, l, mid);
String right = findLCP(strs, mid+1, r);
return compare(left, right);
}
public String compare(String left, String right) {
int max = Math.min(left.length(), right.length());
for(int i=0; i<max; i++) {
if(left.charAt(i) != right.charAt(i)) {
return left.substring(0,i);
}
}
return left.substring(0, max);
}
}
TC: O(n) worst case是n为所有字符串字符数的和,最优情况为 lenOfString * lenOfShortestString.
SC: O(nlogn)
Solution 4: Binary Search
首先找到长度最短的字符串,在对此字符串中的子字符串进行二分匹配
字符串分成两份,前半部分符合common prefix则继续对后半进行二分
如果不符合则对前半部分再进行二分
class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
int minLen = Integer.MAX_VALUE;
for(int i=0; i<strs.length; i++) {
minLen = Math.min(minLen, strs[i].length());
}
int low = 0, high = minLen;
while(low <= high) {
int mid = (low + high) / 2;
if (compare(strs, mid)) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return strs[0].substring(0, (low + high) / 2);
}
public boolean compare(String[] strs, int len) {
String s = strs[0].substring(0, len);
for(int i=0; i<strs.length; i++) {
if(!strs[i].startsWith(s)) {
return false;
}
}
return true;
}
}
TC:O(nlogn)
SC:O(n)