strStr2
原文首发自heliuphy的博客
题目描述
实现时间复杂度为 O(n + m)的方法 strStr。 strStr 返回目标字符串在源字符串中第一次出现的第一个字符的位置. 目标字串的长度为 m , 源字串的长度为 n . 如果目标字串不在源字串中则返回 -1。
样例
输入:source = "abcdef", target = "bcd"
输出:1
解释:
字符串第一次出现的位置为1。
代码
public class Solution {
/*
* @param source: A source string
* @param target: A target string
* @return: An integer as index
*/
public int strStr2(String source, String target) {
// write your code here
if (source == null || target == null) {
return -1;
}
int m = target.length();
int n = source.length();
if (m == 0 && source != null) {
return 0;
}
int targetHash = 0;
int mod = Integer.MAX_VALUE / 33;
for (int i = 0; i < m; i++) {
targetHash = (targetHash * 33 + target.charAt(i) - 'a') % mod;
if (targetHash < 0) {
targetHash += mod; // ---- (1)
}
}
int power33 = 1;
for (int i = 0; i < m - 1; i++) {
power33 = power33 * 33 % mod; // ------ (2)
}
int sourceHash = 0;
for (int i = 0; i < n; i++) { if (i >= m) { // ------ (3)
sourceHash = (sourceHash - (source.charAt(i - m) - 'a') * power33) % mod;
}
sourceHash = (sourceHash * 33 + source.charAt(i) - 'a') % mod; // [1]
if (sourceHash < 0) { sourceHash += mod; } if (i >= m - 1 && sourceHash == targetHash) {
if (target.equals(source.substring(i - m + 1, i + 1))) {
return i - m + 1;
}
}
}
return -1;
}
}
易错点归纳
- 要记得处理 Hash 值 < 0 的情况;
- power33 也要取 mod ,不然也会超出 int 的范围;
- i 应该是即将加入的字母的索引,真正加入在代码 [1] 处。举例:假如 target 的长度为 3,那么在即将加入第 4 个字母的时候才需要删除第一个字母。
常用代码方法小结
对于形式
a m n + b m n − 1 + c m n − 2 + … + d am^{n}+bm^{n-1}+cm^{n-2}+\ldots +d amn+bmn−1+cmn−2+…+d
写代码时可以通过以下形式来避免使用pow()函数。
int value = 0;
for (int i = 0; i <= n; i++) {
value = value * m + char[i];
}
原文首发自heliuphy的博客