leetcode
leetcode 1901 ~ 1950
查找给定哈希值的子串

查找给定哈希值的子串

难度:

标签:

题目描述

代码结果

运行时间: 92 ms, 内存: 18.4 MB


/*
 * Solution Approach:
 * 1. Utilize Java Streams to find the substring with the given hashValue.
 * 2. Convert characters to values and use IntStream to calculate the hash.
 * 3. Find the first matching hash using the Streams API.
 */
import java.util.stream.IntStream;

public class SolutionStream {
    public String subStringWithGivenHash(String s, int power, int modulo, int k, int hashValue) {
        return IntStream.rangeClosed(0, s.length() - k)
                .filter(i -> hash(s.substring(i, i + k), power, modulo) == hashValue)
                .mapToObj(i -> s.substring(i, i + k))
                .findFirst()
                .orElse("");
    }

    private int hash(String sub, int power, int modulo) {
        int hash = 0;
        long powerFactor = 1;
        for (int i = 0; i < sub.length(); i++) {
            hash = (int) ((hash + (sub.charAt(i) - 'a' + 1) * powerFactor) % modulo);
            powerFactor = (powerFactor * power) % modulo;
        }
        return hash;
    }
}

解释

方法:

此题解使用滑动窗口和哈希表来检索特定哈希值的子串。首先,代码创建一个映射mp,用于快速获取字符对应的字母表位置。使用数组f和g来计算子串的哈希值,数组h存储power的幂次模modulo的结果,用于优化计算。数组f从后向前计算当前窗口的哈希值。如果初始窗口的哈希值符合要求,直接返回该子串。否则,使用数组g从前向后递增地添加字符,并重新计算哈希值,检查每次添加后的新窗口哈希值是否符合要求。这种方法有效地避免了重复的计算,通过动态调整窗口来寻找正确的子串。

时间复杂度:

O(n)

空间复杂度:

O(k)

代码细节讲解

🦆
在计算哈希值时,为什么选用了模运算,这里的`modulo`参数具体起到了什么作用?
在计算哈希值时使用模运算(即使用`modulo`参数)主要是为了避免数值溢出并将哈希值控制在一个合理的范围内。由于字符串可能很长,直接计算的哈希值可能非常大,不适合直接使用。通过模运算,我们可以保证所有的哈希值都在0到`modulo-1`之间,这使得哈希值更容易管理和比较。此外,使用模运算还可以减少哈希碰撞的概率,提高算法的效率和准确性。
🦆
数组`h`用于存储`power`的幂次模`modulo`的结果,这样做的主要目的是什么?
数组`h`用于存储`power`的幂次模`modulo`的结果的主要目的是为了优化哈希值的计算。在滑动窗口法中,我们经常需要计算新窗口的哈希值,这通常涉及到多次乘以`power`的操作。预先计算并存储`power`的幂次可以大大减少重复计算,提高整体算法的效率。这种预计算技术是一种常见的时间换空间的优化方法。
🦆
题解中提到,如果初始窗口的哈希值符合要求就直接返回该子串,这里的初始窗口是如何定义的?
在题解中,初始窗口定义为字符串`s`中的第一个长度为`k`的子串。这个窗口从字符串的起始位置开始,长度为`k`,即字符串`s`的前`k`个字符组成的子串。算法首先计算这个初始窗口的哈希值,并与给定的`hashValue`进行比较,如果匹配,则直接返回该子串。如果不匹配,算法继续调整窗口位置,寻找其他可能的匹配子串。
🦆
在动态调整窗口时,使用了两个数组`f`和`g`来计算哈希值,能否详细解释这两个数组的具体作用?
在题解中,数组`f`和`g`被用于计算和更新不同窗口的哈希值,以便动态调整窗口。具体来说,`f`数组用于从当前窗口的末尾开始向前计算每个可能的子窗口的哈希值,这样做可以有效地利用已有的计算结果,从而减少重复计算。而`g`数组则用于从当前窗口的开始向后逐步添加新字符,计算扩展后的新窗口的哈希值。这两个数组的配合使用使得我们可以有效地检查每个新窗口的哈希值,从而找到符合条件的子串。

相关问题