LeetCode-28 實現strStr()
文章目錄
題目描述
給定一個 haystack 字串和一個 needle 字串,在 haystack 字串中找出 needle 字串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。
示例 1:
輸入: haystack = “hello”, needle = “ll”
輸出: 2
示例 2:
輸入: haystack = “aaaaa”, needle = “bba”
輸出: -1
說明:
當 needle 是空字串時,我們應當返回什麼值呢?這是一個在面試中很好的問題。
對於本題而言,當 needle 是空字串時我們應當返回 0 。這與C語言的 strstr() 以及 Java的 indexOf() 定義相符。
我的解法
public int strStr(String haystack, String needle) {
//特殊情況
if(null == needle || "".equals(needle))
return 0;
if(null == haystack || "".equals(haystack)||!haystack.contains(needle))
return -1;
//接下來肯定是haystack包含needle的情況
char needleFirstChar = needle.charAt(0);//獲取needle的第一位字元
int returnInt = haystack.indexOf(needleFirstChar);//找到needle第一位字元在haystack中第一次出現的位置,初始化
String partHaystack = haystack. substring(returnInt,returnInt+needle.length());//partHaystack是從returnInt開始擷取needle長度的字串
while(!needle.equals(partHaystack)){//先判斷partHaystack是否跟指定字串相等
returnInt++;
returnInt += haystack.substring(returnInt).indexOf(needleFirstChar);//取從returnInt之後以為到末尾組成的新字串中,第一次出現needleFirstChar的位置
partHaystack = haystack.substring(returnInt,returnInt+needle.length());//從該位置擷取needle長度的字串用於作比較
}
return returnInt;
}
用間:5ms
戰勝:90.31%
反思
其實String類的contains方法就提供了一個引數為String的類似的方法。不過引數不能為空,否則會報空指標異常“NullPointerException”
/**
* Returns the index within this string of the first occurrence of the
* specified substring.
*
* <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
* this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
* @param str the substring to search for.
* @return the index of the first occurrence of the specified substring,
* or {@code -1} if there is no such occurrence.
*/
public int indexOf(String str) {
return indexOf(str, 0);
}
/**
* Returns the index within this string of the first occurrence of the
* specified substring, starting at the specified index.
*
* <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
* <i>k</i> >= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
* @param str the substring to search for.
* @param fromIndex the index from which to start the search.
* @return the index of the first occurrence of the specified substring,
* starting at the specified index,
* or {@code -1} if there is no such occurrence.
*/
public int indexOf(String str, int fromIndex) {
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
/**
* Code shared by String and StringBuffer to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
*
* @param source the characters being searched.
* @param sourceOffset offset of the source string.
* @param sourceCount count of the source string.
* @param target the characters being searched for.
* @param targetOffset offset of the target string.
* @param targetCount count of the target string.
* @param fromIndex the index to begin searching from.
*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
優化
public int strStr1(String haystack, String needle) {
//特殊情況
if(null == needle || "".equals(needle))
return 0;
else
return haystack.indexOf(needle);
}
用時:6ms(可能電腦及網路效能影響)
戰勝:80.45%
其他思路
我最先想到可以先找到needle首個字元在haystack的位置,在用for迴圈遍歷haystack這個字串needle的長度位的字元,讓他們一一比較,如果不匹配則再找到下一個與needle首個字元一致的字元位置,接著遍歷。這樣可以省去重複建造字串所導致的系統開銷,從而稍稍能縮短執行時間。但其實String類原生的實現方法跟這種方法差不多,具體可以參考一下人家寫的程式碼。
總結
- while迴圈是先判斷後迴圈 ,而do–while迴圈是先迴圈後判斷
- 關於substring的雙參方法substring(a, b),指的是擷取字串 [a,b)左閉右開 位字元
The substring begins at the specified {@code beginIndex} and
extends to the character at index {@code endIndex - 1}.
Thus the length of the substring is {@code endIndex-beginIndex} - 還需多看jdk原始碼