作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/count-the-repetitions/solution/tong-ji-zhong-fu-ge-shu-by-leetcode-solution/
统计重复个数(hard*^*)
题目描述
题解
找出循环节
根据鸽笼原理,最多只要找过 |s2| + 1 个 s1,就一定会出现循环节。
复杂度分析
时间复杂度:
O
(
∣
s
1
∣
∗
∣
s
2
∣
)
O(|s1|*|s2|)
O(∣s1∣∗∣s2∣)。我们最多找过 |s2| + 1 个 s1,就可以找到循环节,最坏情况下需要遍历的字符数量级为
O
(
∣
s
1
∣
∗
∣
s
2
∣
)
O(|s1|*|s2|)
O(∣s1∣∗∣s2∣)。
空间复杂度:
O
(
∣
s
2
∣
)
O(|s2|)
O(∣s2∣)。我们建立的哈希表大小等于 s2 的长度。
代码
class Solution {
public:
int getMaxRepetitions(string s1, int n1, string s2, int n2) {
if(n1 == 0) return 0;
int s1_cnt = 0, index = 0, s2_cnt = 0;
unordered_map<int, pair<int, int>> recall; // 哈希表以S2字符串下标index为索引,存储匹配至第 s1_cnt 个 s1 的末尾,当前匹配到第 s2_cnt 个 s2 中的第 index 个字符时, 已经匹配过的s1 的个数 s1_cnt 和 s2 的个数 s2_cnt 。
pair<int, int> pre_loop, in_loop;
while(1){
++s1_cnt;
for(char ch: s1){
if(ch == s2[index]){
index++;
if(index == s2.size()){
++s2_cnt;
index = 0;
}
}
}
if(s1_cnt == n1)
return s2_cnt/n2;
// 出现之前index,找到循环节
if(recall.count(index)){
auto [s1cnt_prime, s2cnt_prime] = recall[index];
pre_loop = {s1cnt_prime, s2cnt_prime};
in_loop = {s1_cnt - s1cnt_prime, s2_cnt - s2cnt_prime};
break;
}
else
recall[index] = {s1_cnt, s2_cnt};
// ans 存储的是 S1 包含的 s2 的数量,考虑的之前的 pre_loop 和 in_loop
}
int ans = pre_loop.second + (n1 - pre_loop.first) / in_loop.first * in_loop.second;
// S1 的末尾还剩下一些 s1,我们暴力进行匹配
int rest = (n1 - pre_loop.first) % in_loop.first;
for (int i = 0; i < rest; ++i) {
for (char ch: s1) {
if (ch == s2[index]) {
++index;
if (index == s2.size()) {
++ans;
index = 0;
}
}
}
}
// S1 包含 ans 个 s2,那么就包含 ans / n2 个 S2
return ans / n2;
}
};
小结
map与unordered_map内部实现机理
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
优点:有序性;
缺点:空间占用率高。
对于有顺序要求的问题,map效率相对较高。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。哈希表详细介绍
优点: 查找速度快;
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map更高效。
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的