题目描述补充
题目:通用子数组个数
给定两个整数数组 nums1
和 nums2
,以及一个整数 k
。我们称 nums1
的一个子数组 A
是“通用”的,如果子数组 A
的和能够通过重新排列(不一定保持原有顺序)nums2
的某个子数组 B
的元素来得到,且这两个子数组的长度相等。如果 A
的长度至少为 k
,则称 A
为一个“合格”的通用子数组。
你需要计算 nums1
中所有“合格”的通用子数组的个数。
注意:
- 子数组是数组中的一个连续部分。
- 两个数组的元素不一定都是正数或都是负数。
- 数组中的元素范围在 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 示例代码
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 的实现,基本思路相同,但语法和具体实现细节会有所不同。你可以在码小课网站上找到更多相关内容的分享,以学习不同编程语言的实现方法和优化技巧。