You are given an array nums consisting of positive integers.
We call a subarray of an array complete if the following condition is satisfied:
- The number of distinct elements in the subarray is equal to the number of distinct elements in the whole array.
Return the number of complete subarrays.
A subarray is a contiguous non-empty part of an array.
Example 1:
Input: nums = [1,3,1,2,2] Output: 4 Explanation: The complete subarrays are the following: [1,3,1,2], [1,3,1,2,2], [3,1,2] and [3,1,2,2].
Example 2:
Input: nums = [5,5,5,5] Output: 10 Explanation: The array consists only of the integer 5, so any subarray is complete. The number of subarrays that we can choose is 10.
Constraints:
1 <= nums.length <= 10001 <= nums[i] <= 2000
Approach 01:
-
C++
-
Python
#include <vector>
#include <unordered_set>
using namespace std;
class Solution {
public:
int countCompleteSubarrays(vector<int>& nums) {
// Maximum possible value in nums
constexpr int kMaxValue = 2000;
// Total number of distinct elements in the entire array
int totalDistinctCount = unordered_set<int>(nums.begin(), nums.end()).size();
int completeCount = 0;
int windowDistinct = 0;
vector<int> frequency(kMaxValue + 1, 0);
int left = 0;
for (int right = 0; right < nums.size(); ++right) {
int currentNum = nums[right];
if (++frequency[currentNum] == 1)
++windowDistinct; // new distinct enters window
// Shrink window from left until it no longer contains all distinct
while (windowDistinct == totalDistinctCount) {
int leftNum = nums[left++];
if (--frequency[leftNum] == 0)
--windowDistinct;
}
// All subarrays ending at right and starting before 'left' are complete
completeCount += left;
}
return completeCount;
}
};
from typing import List
class Solution:
def countCompleteSubarrays(self, nums: List[int]) -> int:
totalDistinctCount = len(set(nums))
completeCount = 0
windowDistinct = 0
frequency = {}
left = 0
for current in nums:
frequency[current] = frequency.get(current, 0) + 1
if frequency[current] == 1:
windowDistinct += 1 # new distinct enters window
# Shrink window from left until missing a distinct
while windowDistinct == totalDistinctCount:
leftNum = nums[left]
frequency[leftNum] -= 1
left += 1
if frequency[leftNum] == 0:
windowDistinct -= 1
# All subarrays ending at current index and starting before 'left' are complete
completeCount += left
return completeCount
Time Complexity:
- Initial Distinct Count:
Building an
unordered_setof all elements takes \(O(n)\) time. - Sliding Window:
Both pointers
leftandrighteach move at most \(n\) steps → \(O(n)\). - Total Time Complexity:
\(O(n)\), where \(n\) is the length of
nums.
Space Complexity:
- Frequency Array:
Uses a fixed-size array of length \(kMaxValue+1\), which is constant → \(O(1)\).
- Auxiliary Structures:
An
unordered_setto count initial distinct elements of size at most \(n\) → \(O(n)\). - Total Space Complexity:
\(O(n)\).