leetcode
leetcode 401 ~ 450
统计重复个数

统计重复个数

难度:

标签:

题目描述

定义 str = [s, n] 表示 strn 个字符串 s 连接构成。

  • 例如,str == ["abc", 3] =="abcabcabc"

如果可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。

  • 例如,根据定义,s1 = "abc" 可以从 s2 = "abdbec" 获得,仅需要删除加粗且用斜体标识的字符。

现在给你两个字符串 s1 和 s2 和两个整数 n1n2 。由此构造得到两个字符串,其中 str1 = [s1, n1]str2 = [s2, n2]

请你找出一个最大整数 m ,以满足 str = [str2, m] 可以从 str1 获得。

 

示例 1:

输入:s1 = "acb", n1 = 4, s2 = "ab", n2 = 2
输出:2

示例 2:

输入:s1 = "acb", n1 = 1, s2 = "acb", n2 = 1
输出:1

 

提示:

  • 1 <= s1.length, s2.length <= 100
  • s1s2 由小写英文字母组成
  • 1 <= n1, n2 <= 106

代码结果

运行时间: 27 ms, 内存: 16.2 MB


/*
 * 思路:
 * 1. 使用Java Stream构建str1和str2。
 * 2. 构建一个辅助函数check(s1, s2)来判断s2是否是s1的子序列。
 * 3. 使用stream处理字符串的构建和重复的逻辑。
 */
 
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
public class Solution {
    // 辅助函数:判断s2是否是s1的子序列
    public boolean check(String s1, String s2) {
        int j = 0;
        for (int i = 0; i < s1.length() && j < s2.length(); i++) {
            if (s1.charAt(i) == s2.charAt(j)) {
                j++;
            }
        }
        return j == s2.length();
    }
 
    public int getMaxRepetitions(String s1, int n1, String s2, int n2) {
        String longStr1 = IntStream.range(0, n1).mapToObj(i -> s1).collect(Collectors.joining());
        String longStr2 = IntStream.range(0, n2).mapToObj(i -> s2).collect(Collectors.joining());
 
        int m = 0;
        while (check(longStr1, longStr2)) {
            m++;
            longStr2 += s2;
        }
 
        return m;
    }
}
 

解释

方法:

这个题解使用哈希表来记录在 s1 的每个完整循环中,s2 完整出现的次数以及当前匹配到的 s2 的下标。当再次出现相同的 s2 下标时,说明出现了循环节,可以直接计算出在剩余的 s1 循环中,s2 完整出现的次数,从而避免了后续的循环计算。最后将 s2 出现的总次数除以 n2,得到 s2 在 s1 中重复出现的最大次数。

时间复杂度:

O(mn)

空间复杂度:

O(n)

代码细节讲解

🦆
在解决这个问题时,为什么选择使用哈希表来记录每个s2下标对应的s1的循环次数和s2的出现次数?
使用哈希表可以快速检测到s2的某个下标是否在之前的s1循环中已经出现过,并记录下该下标第一次出现时s1的循环次数和s2的出现次数。这样做的目的是为了发现循环节,即一种模式的重复,这种重复可以让我们通过简单的算术运算直接计算出剩余循环中s2的出现次数,而不需要继续逐个匹配s1和s2,从而大大提高算法的效率。
🦆
题解中提到当发现循环节时可以直接计算出剩余的s2出现次数,这种方法的正确性是如何保证的?
当我们在哈希表中发现一个已经存在的s2的下标时,这表示从上一次该下标出现到当前位置,s1和s2之间的匹配形成了一个循环节。这意味着在这个循环节内s1和s2的匹配模式会重复出现。通过记录循环开始和结束时的s1循环次数和s2出现次数,我们可以计算出一个完整循环节中s2出现的次数,并用它来估算总的循环次数内s2的出现次数。这种方法的正确性基于循环节的重复性,即每个循环节s2出现的次数是固定的。
🦆
在题解的实现中,如何处理s2的下标在哈希表中已经存在的情况?请详细解释这一步的逻辑。
当s2的某个下标在哈希表中已经存在时,我们首先提取出这个下标首次出现时和当前的s1循环次数和s2出现次数。这两个点标记了循环节的起始和终止。我们可以通过这两个点计算一个完整循环节中s1和s2的匹配次数。接着,我们可以根据已经完成的s1循环次数和总需求的s1循环次数,来估算还需要多少完整的循环节,以及最后剩余不完整循环节的s1和s2匹配次数。这样就可以计算出总的s2出现次数。
🦆
在哈希表中记录的信息包括s2的下标、s1的循环次数和s2的出现次数,这些信息是如何帮助我们检测到循环节的?
这些信息帮助我们确定了s2的某个下标在s1的多次循环中首次和再次出现的位置。通过比较这两个点的s1循环次数和s2出现次数,我们可以识别出循环节的长度和模式。一旦确定了循环节,我们就可以使用这个信息来预测未来的匹配模式,而不需要继续进行逐字符的匹配。这大大提高了算法处理大数据量时的效率和性能。

相关问题