LeetCode-14 最長公共前綴

題目描述

編寫一個函數來查找字符串數組中的最長公共前綴。

如果不存在公共前綴,返回空字符串 “”。

示例 1:

輸入: [“flower”,“flow”,“flight”]
輸出: “fl”

示例 2:

輸入: [“dog”,“racecar”,“car”]
輸出: “”

解釋: 輸入不存在公共前綴。
說明:

所有輸入只包含小寫字母 a-z 。


我的解法

public String longestCommonPrefix(String[] strs) {
        //特殊情況
        if(null == strs||0 == strs.length)//字符數組爲空的情況
            return "";
        if(1 == strs.length)//數組中只有一個字符串,那麼前綴就是他本身
            return strs[0];

        boolean finalRound = false;
        boolean isPlusIndex = true;
        int index = 0;

        while(!finalRound){
            for(int i=1; i<strs.length; i++){
                if(index > strs[i-1].length() ||index > strs[i].length()){//如果超出某個字符串長度了,終止//這個也同時校驗了某一個字符串爲空的情況
                    finalRound = true;
                    isPlusIndex = false;
                    break;
                }
                if(strs[i-1].substring(0,index).equals(strs[i].substring(0,index))) {

                }  else{//如果前綴不相等了,終止
                    finalRound = true;
                    isPlusIndex = false;
                    break;
                }
            }

            if(isPlusIndex)
                index++;
        }

        return strs[0].substring(0,index-1);//因爲我把最開始假設多了一位“”,所以實際的索引要減去一
    }

用間:9ms
戰勝:77.55%


反思1

  1. 其實可以單拿出數組中第一個字符串作爲標準,讓其與之後的字符串進行比較。如果有相同前綴,第一個字符串必然也有。若前綴不同則可以直接return “”。
  2. 我們在拿第一個字符串爲標準比較前綴的時候。舉個例子,比如第一個字符串和第二字符串前5位都是一致的,但是在跟第三個字符串比較的時候只有前三位一致。也就是說,我們的前綴字節數應該是隨着遍歷的深度越來越少。這樣如果我們還是從字符串的第一個字節開始比較的話,很大機率我們的前幾位字符都是一樣的,這樣就浪費了一些時間。相反我們從字符串的末位字符開始比較,則很快能篩掉不一致的字符。

優化1

public String longestCommonPrefix3(String[] strs) {
       if(strs.length == 0) return "";
       String prefix = strs[0];
       for (int i = 0; i <= strs.length - 1; i++){
           while(!strs[i].startsWith(prefix)){
               prefix = prefix.substring(0,prefix.length()-1);
           }
       }
       return prefix;
   }

用時:9ms
戰勝:77.55%
==! 在我的電腦上並沒有看出太大的差距


反思2

  1. 首先我們拿第一個字符串作爲標準,就沒有必要再讓他跟自己比較了
  2. 如果發現沒有公共前綴,直接跳出循環,減少系統開銷

優化2

public String longestCommonPrefix4(String[] strs) {
       if(strs.length == 0 || strs[0].length() == 0) return "";
       String prefix = strs[0];
       for (int i = 1; i <= strs.length - 1; i++){
           if(!"".equals(prefix)){
               while(!strs[i].startsWith(prefix)){
                   prefix = prefix.substring(0,prefix.length()-1);
               }
           }
       }
       return prefix;
   }

用時:6ms
戰勝:98.61%


其他思路

我比較喜歡這優化的版本,雖然leetcode上有更快的版本(並沒有覺得有什麼可圈可點的地方,跑出了4ms估計是網絡電腦的原因,我本機還是跑了9ms)。但是少量的代碼更加意味着思路的清晰。有時候這纔是更重要的。


總結

有的時候找前面相似的問題,從末位排除是更好的辦法。


Github

LeetCode刷題筆記

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章