leetcode.windliang.cc/ 第一時間發佈java
咱們把全部字符串垂直排列,而後一列一列的比較,直到某一個字符串到達結尾或者該列字符不徹底相同。數組
下邊看一下個人代碼,看起來比較多函數
//這個函數判斷 index 列的字符是否徹底相同
public boolean isSameAtIndex(String[] strs, int index) {
int i = 0;
while (i < strs.length - 1) {
if (strs[i].charAt(index) == strs[i + 1].charAt(index)) {
i++;
} else {
return false;
}
}
return true;
}
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0)
return "";
//獲得最短的字符串的長度
int minLength = Integer.MAX_VALUE;
for (int i = 0; i < strs.length; i++) {
if (strs[i].length() < minLength) {
minLength = strs[i].length();
}
}
int j = 0;
//遍歷全部列
for (; j < minLength; j++) {
//若是當前列字符不徹底相同,則結束循環
if (!isSameAtIndex(strs, j)) {
break;
}
}
return strs[0].substring(0, j);
}
複製代碼
下邊看一下,官方的代碼spa
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
//遍歷全部列
for (int i = 0; i < strs[0].length() ; i++){
char c = strs[0].charAt(i); // 保存 i 列第 0 行的字符便於後續比較
//比較第 1,2,3... 行的字符和第 0 行是否相等
for (int j = 1; j < strs.length; j ++) {
/** * i == strs[j].length() 代表當前行已經到達末尾 * strs[j].charAt(i) != c 當前行和第 0 行字符不相等 * 上邊兩種狀況返回結果 */
if (i == strs[j].length() || strs[j].charAt(i) != c)
return strs[0].substring(0, i);
}
}
return strs[0];
}
複製代碼
時間複雜度:最壞的狀況就是 n 個 長度爲 m 的徹底同樣的字符串,假設 S 是全部字符的和,那麼 S = m * n,時間複雜度就是 O(S)。固然正常狀況下並不須要比較全部字符串,最多比較 n * minLen 個字符就能夠了。code
空間複雜度:O(1),常數個額外空間。cdn
咱們將字符串水平排列,第 0 個和第 1 個字符串找最長子串,結果爲 leet,再把結果和第 2 個字符串比較,結果爲 leet,再把結果和第 3 個字符串比較,結果爲 lee,即爲最終結果。blog
public String longestCommonPrefix3(String[] strs) {
if (strs.length == 0)
return "";
String prefix = strs[0]; // 保存結果
// 遍歷每個字符串
for (int i = 1; i < strs.length; i++) {
// 找到上次獲得的結果 prefix 和當前字符串的最長子串
int minLen = Math.min(prefix.length(), strs[i].length());
int j = 0;
for (; j < minLen; j++) {
if (prefix.charAt(j) != strs[i].charAt(j)) {
break;
}
}
prefix = prefix.substring(0, j);
}
return prefix;
}
複製代碼
時間複雜度:最壞狀況和解法一是同樣,n 個長度爲 m 的徹底相同的字符,就要比較全部的字符 S,S = n * m 。但對於正常狀況,處於最短字符串前的字符串依舊要比較全部字符,而不是最短字符串個字符,相對於解法一較差。遞歸
空間複雜度:O(1)。leetcode
咱們把原來的數組分紅兩部分,求出左半部分的最長公共前綴,求出右半部分的最長公共前綴,而後求出的兩個結果再求最長公共前綴,就是最後的結果了。字符串
求左半部分的最長公共前綴,咱們能夠繼續把它分紅兩部分,按照上邊的思路接着求。而後一直分紅兩部分,遞歸下去。
直到該部分只有 1 個字符串,那麼最長公共子串就是它自己了,直接返回就能夠了。
public String longestCommonPrefix(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);
}
複製代碼
時間複雜度:
空間複雜度:
每次遇到遞歸的狀況,老是有些理不清楚,先空着吧。
進行了垂直比較和水平比較,又用到了遞歸,solution 裏還介紹了二分查找,感受這裏用二分查找有些太僵硬了,反而使得時間複雜度變高了。還介紹了前綴樹,這裏後邊遇到再總結吧。