LeetCode-28 实现strStr()

版权声明:http://blog.csdn.net/jarwis https://blog.csdn.net/jarwis/article/details/85884625

题目描述

给定一个 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> &gt;= 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类原生的实现方法跟这种方法差不多,具体可以参考一下人家写的代码。


总结

  1. while循环是先判断后循环 ,而do–while循环是先循环后判断
  2. 关于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}

  3. 还需多看jdk源码

Github

LeetCode刷题笔记

猜你喜欢

转载自blog.csdn.net/jarwis/article/details/85884625