[28] Implement strStr()

1. 題目描述

Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

給定兩個字符串,判斷一個字符串是不是另一個字符串的子串,如果是返回第一個字串位置,如果不是返回-1。

2. 解題思路

String自帶一個函數叫做indexOf,並且有兩種重載,一種爲indexOf(String str),另一種爲indexOf(String str, int fromIndex),第一種是從0開始匹配,第二種是從給定的位置開始匹配,第一種內部通過調用indexOf(str, 0)來實現。
那麼到底這個函數內部是怎麼實現的呢?
源碼中的主要思想是,使用一個i先找到第一個匹配的位置,然後檢查之後的串與子串匹配不匹配,匹配直接返回i,遇到不匹配的從i+1開始繼續匹配。
當然源碼中還包括一些邊界上的考慮,起始不太明白他裏面給的Offset是要幹嘛,默認不都是0嘛,後來理解了一下,可能是因爲我這個需求可以是給定的source就是子串,給定的target也是個子串,這樣就可以用Offset進行截取啦,但是爲啥只有左邊的沒有右邊的呢?而且當前源碼並沒有對於offset的驗證,那麼如果傳入負值,直接就崩啦。但是這個方法是一個沒有聲明可見性的方法,那麼他是一個僅java.lang包內可見的方法,可能不太需要驗證吧。

3. Code

public class Solution {
    public int strStr(String haystack, String needle)
    {
        // 直接使用indexOf
        return haystack.indexOf(needle);
    }
}
// indexOf(String str)源碼,返回str第一次出現的位置,如果從未出現返回-1
    /**
     * 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);
    }
// indexOf(String str, int fromIndex)源碼,返回從fromIndex起第一次出現位置,沒有出現過返回-1
    /**
     * 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> &gt;= fromIndex && 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) {
            // 如果目標char數組爲空,返回最後一個值,如果不爲空返回-1
            return (targetCount == 0 ? sourceCount : -1);
        }
        // 如果開始查找的位置小於0,將開始查找的位置修正爲0
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        // 如果目標char數組爲空,返回第0個位置就匹配了
        if (targetCount == 0) {
            return fromIndex;
        }
        // 左邊界是第一個元素
        char first = target[targetOffset];
        // 右邊界爲源串的左邊界+(源串的長度-目標串的長度)
        int max = sourceOffset + (sourceCount - targetCount);
        // 起始i=源串的左邊界+開始匹配位置
        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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章