📌  相关文章
📜  恰好具有 K 个完全平方数的子数组的计数(1)

📅  最后修改于: 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, 10,000]。
  • 给定的 k 为 [1, 100]。
  • 给定的数组中元素在 [-10,000, 10,000] 之间。

解题思路

在做这道题之前,我们需要对完全平方数有一个基本的了解。完全平方数就是整数的平方,例如 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 个完全平方数的子数组的数量。