当前位置: 面试刷题>> 通用子数组个数 (经典算法题500道)
### 题目描述补充
**题目:通用子数组个数**
给定两个整数数组 `nums1` 和 `nums2`,以及一个整数 `k`。我们称 `nums1` 的一个子数组 `A` 是“通用”的,如果子数组 `A` 的和能够通过重新排列(不一定保持原有顺序)`nums2` 的某个子数组 `B` 的元素来得到,且这两个子数组的长度相等。如果 `A` 的长度至少为 `k`,则称 `A` 为一个“合格”的通用子数组。
你需要计算 `nums1` 中所有“合格”的通用子数组的个数。
**注意**:
1. 子数组是数组中的一个连续部分。
2. 两个数组的元素不一定都是正数或都是负数。
3. 数组中的元素范围在 32 位有符号整数内。
### 示例
**输入**:
- `nums1 = [1, 2, 3, 2, 1]`
- `nums2 = [2, 3, 4]`
- `k = 3`
**输出**:
- `2`
**解释**:
- `[1, 2, 3]` 是一个通用子数组,因为 `nums2` 中的 `[2, 3]` 子数组可以通过重新排列得到 `[1, 2, 3]` 的和(均为 6)。
- `[2, 1, 2]` 也是一个通用子数组,因为 `nums2` 中的 `[3, 2]` 子数组可以通过重新排列得到 `[2, 1, 2]` 的和(均为 5)。
### PHP 示例代码
```php
function numSubarraysWithSumK($nums1, $nums2, $k) {
$count = 0;
$sums1 = array();
$sums2 = array();
// 计算 nums2 所有子数组的和及出现的次数
helper($nums2, $sums2, 0, 0);
$sum = 0;
$prefixSums = array(0 => 1); // 用于记录 nums1 的前缀和及出现次数
for ($i = 0; $i < count($nums1); $i++) {
$sum += $nums1[$i];
for ($j = $i; $j >= max(0, $i - $k + 1); $j--) {
$target = $sum - ($j == 0 ? 0 : $prefixSums[$j-1]['sum']);
if (isset($sums2[$target])) {
$count += $sums2[$target];
}
}
if (!isset($prefixSums[$sum])) {
$prefixSums[$sum] = array('sum' => $sum, 'count' => 0);
}
$prefixSums[$sum]['count']++;
}
return $count;
}
// 辅助函数,计算 nums2 的所有子数组和及其出现次数
function helper(&$nums, &$sums, $start, $currentSum) {
$sums[$currentSum] = isset($sums[$currentSum]) ? $sums[$currentSum] + 1 : 1;
if ($start < count($nums)) {
helper($nums, $sums, $start + 1, $currentSum + $nums[$start]);
}
}
// 使用示例
$nums1 = [1, 2, 3, 2, 1];
$nums2 = [2, 3, 4];
$k = 3;
echo numSubarraysWithSumK($nums1, $nums2, $k); // 输出 2
```
**注意**:上述 PHP 示例代码为了简化,直接使用了递归辅助函数来计算 `nums2` 的所有子数组和,这在实际应用中可能效率不高,特别是对于大数据集。可以考虑使用更高效的算法,如前缀和加哈希表等。
对于 Python 和 JavaScript 的实现,基本思路相同,但语法和具体实现细节会有所不同。你可以在码小课网站上找到更多相关内容的分享,以学习不同编程语言的实现方法和优化技巧。