含最多 K 个可整除元素的子数组
难度:
标签:
题目描述
代码结果
运行时间: 52 ms, 内存: 16.8 MB
/*
* 思路:
* 1. 使用 Java Stream 生成所有可能的子数组。
* 2. 对每个子数组进行过滤,确保被 p 整除的元素个数不超过 k。
* 3. 使用 Set 来存储这些子数组的字符串表示,确保唯一性。
* 4. 返回 Set 的大小。
*/
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.IntStream;
public class Solution {
public int countDistinctSubarrays(int[] nums, int k, int p) {
Set<String> uniqueSubarrays = new HashSet<>();
IntStream.range(0, nums.length).forEach(i ->
IntStream.rangeClosed(i, nums.length - 1).forEach(j -> {
int[] subarray = Arrays.copyOfRange(nums, i, j + 1);
long count = Arrays.stream(subarray).filter(x -> x % p == 0).count();
if (count <= k) uniqueSubarrays.add(Arrays.toString(subarray));
})
);
return uniqueSubarrays.size();
}
}
解释
方法:
这个题解利用了两步主要的算法技巧来解决问题:首先,它使用了双指针技术来计算所有可能的符合条件的子数组的数量。具体来说,外层循环遍历数组,内层循环扩展直到子数组中可以被p整除的元素数量超过k为止。在每次外层循环中,计算从当前索引起始的、满足条件的子数组数量,并逐步减少被p整除的元素的计数。其次,利用后缀数组来识别重复的子数组。构建后缀数组并计算最长公共前缀(LCP),从而可以快速确定哪些子数组是重复的。最后,将找到的总子数组数减去重复的子数组数,得到答案。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在双指针技术中,如何确保在移动内层循环的指针j时,正确地更新和管理可被p整除的元素的计数?
▷🦆
题解中提到使用后缀数组来识别重复的子数组,请问如何通过后缀数组和最长公共前缀(LCP)来识别和计算重复的子数组数量?
▷🦆
在使用后缀数组处理时,初始化排名数组为字符数组时,如何处理整数数组?是否需要将整数转换为字符,或是使用其他方法?
▷