Leetcode-2799. 统计完全子数组的数目

Problem: 2799. 统计完全子数组的数目

思路

滑动窗口

解题过程

首先需要明确数组中的唯一值个数,通过插入集合后统计集合长度得到唯一值个数为k。

维护一个窗口[l, r],遍历右端点。当遍历到r时,通过哈希表对元素进行计数,如果此时哈希表的长度为k,也就意味着包含所有的元素,此时是一个完全子数组

由于子数组越长,越能满足题目要求,所以除了 [l,r],还有 [l−1,r],[l−2,r],…,[0,r] 都是满足要求的。为了计数,我们需要最大化l,也就是将l左移,在此过程中,不断计算cnt[nums[l]]的值,如果为0,一定要在哈希表中删除该元素,这样才能更新哈希表的长度,也就是判断当前数组是否是完美子数组的依据。此时更新后的l左侧所有的元素作为起始节点的子数组,都满足右端点是r时是完全子数组。

更新结果:ans += l从0到l-1长度为l。

Code

python

class Solution:
    def numberOfSubstrings(self, s: str, k: int) -> int:
        n = len(s)
        l = ans = 0
        cnt = defaultdict(int)

        for r, ch in enumerate(s):
            cnt[ch] += 1
            while cnt[ch] == k:
                cnt[s[l]] -= 1
                l += 1
            ans += l

        return ans

c++

class Solution {
public:
    int countCompleteSubarrays(vector& nums) {
        int n = nums.size();
        int l = 0;
        int ans = 0;
        set uni_elem(nums.begin(), nums.end());
        int k = uni_elem.size();

        unordered_map cnt;

        for(int r = 0; r < n; r ++){
            cnt[nums[r]] ++;
            while(cnt.size() == k){
                cnt[nums[l]] --;
                if(cnt[nums[l]] == 0){
                    cnt.erase(nums[l]);
                }
                l ++;
            }
            ans += l;
        }
        return ans;
    }
};

复杂度

  • 时间复杂度: O(nlogN),插入 set 的时间复杂度为 O(n log n)(每个插入操作是 O (log n),共 n 次)
  • 空间复杂度: O(k), 其中 k 是数组中不同元素的数量

    你可能感兴趣的:(Leetcode,#滑动窗口,算法,数据结构)