leetcode之hot100---和为K的子数组(C++)

思路一:暴力解法

我们通过维护一个动态的滑动窗口来解决问题。滑动窗口的范围由两个指针控制,一个指针表示窗口的起始位置(左边界),另一个指针表示窗口的结束位置(右边界)。窗口内的元素和会随着窗口范围的变化而动态调整。

具体逻辑如下:

  1. 初始化窗口和:从窗口的左边界开始,逐步扩展右边界,计算窗口内的元素和。
  2. 判断窗口和
  • 如果窗口内的元素和等于目标值,则说明这个窗口满足要求,计数器 num 加 1,并尝试扩展窗口。
  • 如果窗口和小于目标值,说明当前窗口还不够大,需要继续扩展右边界以包含更多元素。
  • 如果窗口和大于目标值,说明窗口内的元素过多,需要缩小窗口,即移动左边界。不断调整窗口的范围,直到右边界遍历完整个数组。

最终,num 就是所有满足条件的子数组个数。

虽然可以编译成功,但是超出时间限制了 

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int num = 0;//记录满足条件的个数
        int n = nums.size();
        for(int i = 0; i < n; i++){
            int left = i;//动态窗口的左边界索引
            int right = left;//动态窗口的左边界索引
            int sum = 0;
            while(right >= 0){
                sum += nums[right];
                if(sum == k){
                    num++;
                }
                right--;
                
            }

        }
        return num;
        
    }
};

思路二:哈希表法

遍历数组,计算当前位置的累积和(前缀和),并通过当前前缀和 - 目标值来判断是否存在满足条件的子数组。

为快速查找之前的前缀和,我们用哈希表记录每个前缀和出现的次数:

  1. 如果 当前前缀和 - 目标值 在哈希表中存在,说明有对应的子数组满足条件,将其出现次数加到结果中。
  2. 更新哈希表,记录当前前缀和的出现次数。

最终,结果即为满足条件的子数组个数。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
               
        unordered_map<int, int> hashMap;
        hashMap[0]  = 1;//初始化哈希表
        int n = nums.size();
        int sum = 0;//记录哈希表的键
        int count = 0;//记录哈希表的值
        for(int i = 0; i < n; i++){
            sum += nums[i];
            //在哈希表中找到满足条件的子数组
            if(hashMap.find(sum - k) != hashMap.end()){
                count += hashMap[sum - k];
            }
            hashMap[sum]++;//更新哈希表的值,即前缀和出现次数,确保每个子数组都被遍历到
            
        }
        return count;
        
    }
};

 初始化哈希表的作用是,如果遇到数组中单个数满足目标值的情况,确保在值为0时,哈希表中存有对应的值,举个例子,当nums = [1,2,3], k = 1时,满足条件的子数组为nums[0],此处的前缀和为1,即哈希表的键为1,此时执行count+=hashMap[sum-k]时就需要用到hashMap[0]=1

⚠️满足条件的子数组可能是单个元素,也有可能是多个元素组成的子数组,在进行计数时,第一种情况得到的结果是sum - k = 0,第二种情况得到的结果是sum - k = 数组中某个前缀和,此时只需要查询哈希表,便可以得到想要的结果,在计算前缀和时虽然从数组中第一个元素开始遍历,但是实际上是在寻找一个合适的“起点”,使得以当前点 i 为“终点”的子数组和为 k。这涵盖了所有可能的子数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值