leetCode 14 Longest Common Prefix

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 裏還介紹了二分查找,感受這裏用二分查找有些太僵硬了,反而使得時間複雜度變高了。還介紹了前綴樹,這裏後邊遇到再總結吧。

相關文章
相關標籤/搜索