題目描述
編寫一個函數來查找字符串數組中的最長公共前綴。
如果不存在公共前綴,返回空字符串 “”。
示例 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
- 其實可以單拿出數組中第一個字符串作爲標準,讓其與之後的字符串進行比較。如果有相同前綴,第一個字符串必然也有。若前綴不同則可以直接return “”。
- 我們在拿第一個字符串爲標準比較前綴的時候。舉個例子,比如第一個字符串和第二字符串前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
- 首先我們拿第一個字符串作爲標準,就沒有必要再讓他跟自己比較了
- 如果發現沒有公共前綴,直接跳出循環,減少系統開銷
優化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)。但是少量的代碼更加意味着思路的清晰。有時候這纔是更重要的。
總結
有的時候找前面相似的問題,從末位排除是更好的辦法。