2799.统计完全子数组的数目:滑动窗口(哈希表)

【LetMeFly】2799.统计完全子数组的数目:滑动窗口(哈希表)

力扣题目链接:https://leetcode.cn/problems/count-complete-subarrays-in-an-array/

给你一个由 整数组成的数组 nums

如果数组中的某个子数组满足下述条件,则称之为 完全子数组

  • 子数组中 不同 元素的数目等于整个数组不同元素的数目。

返回数组中 完全子数组 的数目。

子数组 是数组中的一个连续非空序列。

 

示例 1:

输入:nums = [1,3,1,2,2]
输出:4
解释:完全子数组有:[1,3,1,2]、[1,3,1,2,2]、[3,1,2] 和 [3,1,2,2] 。

示例 2:

输入:nums = [5,5,5,5]
输出:10
解释:数组仅由整数 5 组成,所以任意子数组都满足完全子数组的条件。子数组的总数为 10 。

 

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 2000

解题方法:滑动窗口

首先使用一个哈希表统计数组中出现了多少种的元素(记为allType)。

接着再使用一个哈希表,统计窗口中每个元素出现多少次。

数组中的元素依次加入窗口中,当窗口中元素种类数为allType并且窗口中第一个元素出现次数不为1时,左移窗口左指针。

这样,就保证了每次窗口右指针确定时,左指针指向位置为最后一个“窗口合法”的位置(或0)。

  • 时间复杂度$O(len(nums))$
  • 空间复杂度$O(len(nums))$

AC代码

C++

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
/*
* @Author: LetMeFly
* @Date: 2025-04-24 22:47:03
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-04-24 23:05:27
* @Description: AC,36.08%,63.38%
*/
class Solution {
public:
int countCompleteSubarrays(vector<int>& nums) {
unordered_set<int> visited;
for (int t : nums) {
visited.insert(t);
}
int allType = visited.size();
unordered_map<int, int> times;
int ans = 0;
for (int l = 0, r = 0; r < nums.size(); r++) {
times[nums[r]]++;
while (times.size() == allType && times[nums[l]] > 1) {
times[nums[l++]]--;
}
if (times.size() == allType) {
ans += l + 1;
}
}
return ans;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'''
Author: LetMeFly
Date: 2025-04-24 22:47:44
LastEditors: LetMeFly.xyz
LastEditTime: 2025-04-24 23:10:14
Description: AC,60.65%,29.08%
'''
from typing import List
from collections import defaultdict

class Solution:
def countCompleteSubarrays(self, nums: List[int]) -> int:
allType = len(set(nums))
times = defaultdict(int)
l = ans = 0
for r in range(len(nums)):
times[nums[r]] += 1
while len(times) == allType and times[nums[l]] > 1:
times[nums[l]] -= 1
l += 1
if len(times) == allType:
ans += l + 1
return ans

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
/*
* @Author: LetMeFly
* @Date: 2025-04-24 22:47:48
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-04-24 23:18:36
* @Description: AC,65.83%,85.83%
*/
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.HashMap;

class Solution {
public int countCompleteSubarrays(int[] nums) {
Set<Integer> se = new HashSet<>();
for (int t : nums) {
se.add(t);
}
int allType = se.size();
Map<Integer, Integer> times = new HashMap<>();
int ans = 0;
int l = 0;
for (int t : nums) {
times.merge(t, 1, Integer::sum);
while (times.size() == allType && times.get(nums[l]) > 1) {
times.merge(nums[l++], -1, Integer::sum);
}
if (times.size() == allType) {
ans += l + 1;
}
}
return ans;
}
}

Go

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
/*
* @Author: LetMeFly
* @Date: 2025-04-24 22:47:30
* @LastEditors: LetMeFly.xyz
* @LastEditTime: 2025-04-24 23:23:21
* @Description: AC,32.53%,40.96%
*/
package main

func countCompleteSubarrays(nums []int) (ans int) {
visited := map[int]bool{}
for _, t := range nums {
visited[t] = true
}
allType := len(visited)
times := map[int]int{}
l := 0
for _, t := range nums {
times[t]++
for len(times) == allType && times[nums[l]] > 1 {
times[nums[l]]--
l++
}
if len(times) == allType {
ans += l + 1
}
}
return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


2799.统计完全子数组的数目:滑动窗口(哈希表)
https://blog.letmefly.xyz/2025/04/24/LeetCode 2799.统计完全子数组的数目/
作者
发布于
2025年4月24日
许可协议