📌  相关文章
📜  计算每个不同元素至少出现两次的子数组(1)

📅  最后修改于: 2023-12-03 14:57:33.397000             🧑  作者: Mango

题目介绍

给定一个整数数组,计算出所有元素至少出现两次的子数组的个数。

例如,给定数组 [1, 2, 1, 3, 2],满足要求的子数组为 [1, 2, 1], [2, 1, 3, 2], [1, 3, 2],共三个子数组。

解题思路

本题的解题思路是使用滑动窗口算法。从左往右扫描数组,维护一个滑动窗口,使得窗口里的元素至少出现两次。

对于窗口右端点 r,我们需要找到左端点 l,使得 [l, r] 所包含的元素都至少出现两次。因为是计算子数组个数,所以我们可以直接统计以 r 结尾的符合要求的子数组个数,然后加到答案中即可。

对于窗口右端点 r,假设它包含 k 种不同的元素,那么一共有 k(k-1)/2 种不同元素的组合,这些组合都可能是满足要求的子数组。我们只需要枚举每一种组合,然后找到最左边和最右边的两个位置,中间的所有元素都至少出现两次,这样就可以计算出该组合对应的子数组个数。

时间复杂度为 O(n)。

代码实现

def count_subarrays(nums):
    n = len(nums)
    freq = [0] * (n + 1)
    l = r = res = cnt = uniq_cnt = 0

    for r in range(n):
        if freq[nums[r]] == 0:
            uniq_cnt += 1
        freq[nums[r]] += 1

        while freq[nums[l]] > 1:
            freq[nums[l]] -= 1
            l += 1

        if uniq_cnt >= 2:
            res += r - l + 1

        cnt += uniq_cnt * (uniq_cnt - 1) // 2

        while uniq_cnt > 2:
            freq[nums[l]] -= 1
            if freq[nums[l]] == 0:
                uniq_cnt -= 1
            l += 1

    cnt += uniq_cnt * (uniq_cnt - 1) // 2
    return res - cnt

以上就是本题的解法,希望能对大家的编程学习和面试备考起到一些帮助。