子数组不同元素数目的平方和 II
难度:
标签:
题目描述
You are given a 0-indexed integer array nums
.
The distinct count of a subarray of nums
is defined as:
- Let
nums[i..j]
be a subarray ofnums
consisting of all the indices fromi
toj
such that0 <= i <= j < nums.length
. Then the number of distinct values innums[i..j]
is called the distinct count ofnums[i..j]
.
Return the sum of the squares of distinct counts of all subarrays of nums
.
Since the answer may be very large, return it modulo 109 + 7
.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [1,2,1] Output: 15 Explanation: Six possible subarrays are: [1]: 1 distinct value [2]: 1 distinct value [1]: 1 distinct value [1,2]: 2 distinct values [2,1]: 2 distinct values [1,2,1]: 2 distinct values The sum of the squares of the distinct counts in all subarrays is equal to 12 + 12 + 12 + 22 + 22 + 22 = 15.
Example 2:
Input: nums = [2,2] Output: 3 Explanation: Three possible subarrays are: [2]: 1 distinct value [2]: 1 distinct value [2,2]: 1 distinct value The sum of the squares of the distinct counts in all subarrays is equal to 12 + 12 + 12 = 3.
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 105
代码结果
运行时间: 3006 ms, 内存: 87.3 MB
/*
* 题目思路:
* 使用Java Stream和集合类来计算所有子数组的不同计数值的平方和。
* 将滑动窗口和哈希表的逻辑用Java Stream表示出来,
* 并且使用Stream API来处理数组和集合。
*/
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
public int sumOfSquaredDistinctCounts(int[] nums) {
int n = nums.length;
int MOD = 1000000007;
long result = 0;
for (int i = 0; i < n; i++) {
Set<Integer> distinctElements = new HashSet<>();
for (int j = i; j < n; j++) {
distinctElements.add(nums[j]);
int distinctCount = distinctElements.size();
result = (result + (long) distinctCount * distinctCount) % MOD;
}
}
return (int) result;
}
}
解释
方法:
该题解采用了线段树结合延迟更新的技巧来处理子数组不同元素数目的计算。首先,线段树用于高效地管理和更新子数组的不同元素数目。延迟更新机制用于在必要时批量更新子数组信息,以提高效率。算法的核心在于维护每个元素最后一次出现的位置,并使用线段树在每次遍历新元素时,更新该元素之后的所有子数组的不同元素计数。这样,每遍历一个新元素,就可以计算出以该元素结尾的所有子数组的不同元素计数增量,并累加到结果中。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在实现线段树时,你是如何选择线段树大小为数组长度的四倍的?这样的大小是否总是足够或有时过度?
▷🦆
你提到了延迟更新(lazy propagation)技术,能否详细解释这种技术在解决此类问题中的具体作用和实现方法?
▷🦆
算法中涉及到数组`d`用于记录每个元素最后一次出现的位置,请问这个数组的维护是否会影响整体算法的效率,如果会,如何优化?
▷