28. 实现strStr()

题目

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例1:

1
2
输入: haystack = "hello", needle = "ll"
输出: 2

示例2:

1
2
输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

解法

解法一:暴力破解

直接比较子字符串是否相等

Java

1
2
3
4
5
6
7
8
9
10
public int strStr(String haystack, String needle) {
int L = needle.length(), n = haystack.length();

for (int start = 0; start < n - L + 1; ++start) {
if (haystack.substring(start, start + L).equals(needle)) {
return start;
}
}
return -1;
}

解法二:

  1. 移动 pn 指针,直到 pn 所指向位置的字符与 needle 字符串第一个字符相等。
  2. 通过 pn,pL,curr_len 计算匹配长度。
  3. 如果完全匹配(即 curr_len == L),返回匹配子串的起始坐标(即 pn - L)。
  4. 如果不完全匹配,回溯。使 pn = pn - curr_len + 1, pL = 0, curr_len = 0。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public int strStr(String haystack, String needle) {
int L = needle.length(), n = haystack.length();
if (L == 0) return 0;

int pn = 0;
while (pn < n - L + 1) {
// find the position of the first needle character
// in the haystack string
while (pn < n - L + 1 && haystack.charAt(pn) != needle.charAt(0)) ++pn;

// compute the max match string
int currLen = 0, pL = 0;
while (pL < L && pn < n && haystack.charAt(pn) == needle.charAt(pL)) {
++pn;
++pL;
++currLen;
}

// if the whole needle string is found,
// return its start position
if (currLen == L) return pn - L;

// otherwise, backtrack
pn = pn - currLen + 1;
}
return -1;
}

解法三:

比较haystack中和needle相等的字串的哈希码和needle的哈希码是否相等

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
// function to convert character to integer
public int charToInt(int idx, String s) {
return (int)s.charAt(idx) - (int)'a';
}

public int strStr(String haystack, String needle) {
int L = needle.length(), n = haystack.length();
if (L > n) return -1;

// base value for the rolling hash function
int a = 26;
// modulus value for the rolling hash function to avoid overflow
long modulus = (long)Math.pow(2, 31);

// compute the hash of strings haystack[:L], needle[:L]
long h = 0, ref_h = 0;
for (int i = 0; i < L; ++i) {
h = (h * a + charToInt(i, haystack)) % modulus;
ref_h = (ref_h * a + charToInt(i, needle)) % modulus;
}
if (h == ref_h) return 0;

// const value to be used often : a**L % modulus
long aL = 1;
for (int i = 1; i <= L; ++i) aL = (aL * a) % modulus;

for (int start = 1; start < n - L + 1; ++start) {
// compute rolling hash in O(1) time
h = (h * a - charToInt(start - 1, haystack) * aL
+ charToInt(start + L - 1, haystack)) % modulus;
if (h == ref_h) return start;
}
return -1;
}
}

参考资料

LeetCode-实现strStr()题解

0%