📅  最后修改于: 2023-12-03 14:54:21.077000             🧑  作者: Mango
题目描述:
给定一个整数数组 nums 和一个整数 k,请找到该数组中恰好包含 k 个完全平方数的子数组的数量。
示例:
输入: nums = [1,2,3,4,5], k = 1 输出: 1 解释: [1] 是唯一一个包含 1 个完全平方数的子数组。
输入: nums = [1,2,3,4,5,6,7,8,9], k = 3 输出: 2 解释: [1,2,3], [4,5,6] 是唯一两个包含 3 个完全平方数的子数组。
提示:
在做这道题之前,我们需要对完全平方数有一个基本的了解。完全平方数就是整数的平方,例如 1, 4, 9, 16, 25 等等。我们可以先将原始数组中的每个数平方,然后再按照子数组的方式进行枚举,看看有多少个子数组中包含了恰好 k 个平方数。
然而,我们并不需要将原始数组中的每个数都平方,因为平方后的数值是比较大的。相反,我们可以使用前缀和来加速计算,我们使用 sum[i] 表示原始数组中前 i 个元素的平方和,这样计算任何一个子数组的平方和之差也就变成了 sum[j] - sum[i - 1]。对于这样一个差值,我们就需要在中间的子数组中找到恰好 k 个数。
因此,我们可以通过枚举子数组的方式来找到符合要求的数组。具体来说,我们可以使用双指针来维护,左右指针之间的平方和的差值等于恰好 k 个完全平方数。当然,我们也可以使用哈希表来维护前缀和的数量。因为任何时候,我们只需要查找前面的前缀和,然后就可以知道中间的子数组查找的数量。
class Solution {
public:
int numSubarrayWithKSum(vector<int>& nums, int k) {
unordered_map<int, int> count;
int sum = 0, ans = 0;
count[0] = 1; // 处理前缀和本身就是平方数的情况
for (int i = 0; i < nums.size(); i++) {
sum += nums[i] * nums[i];
if (count.find(sum - k) != count.end()) {
ans += count[sum - k];
}
count[sum]++;
}
return ans;
}
};
题目要求我们找到恰好包含 k 个完全平方数的子数组的数量,首先我们需要对完全平方数做一个基本的了解,然后再使用前缀和进行枚举,按照子数组的方式计算每个子数组的平方和。最后,使用双指针或哈希表进行查找,找到恰好包含 k 个完全平方数的子数组的数量。