560. 和为K的子数组

题目:
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1][1,1] 为两种不同的情况。

方法一:暴力
遇到不会的题目首先要想到一种暴力解法,然后再慢慢优化,本题用暴力解法可以通过,但是也要注意。本题的一种暴力解法显而易见,即可以从元素 i i i开始计算 n u m s [ i ] nums[i] nums[i] n u m s [ e n d ] nums[end] nums[end]的和,如果 n u m s [ i ] nums[i] nums[i] n u m s [ j ] nums[j] nums[j]的和恰好等于 k k k那么 n u m s [ i : j ] nums[i:j] nums[i:j]为一个满足条件的子序列。代码如下,需要十分注意的是size = nums.size() 用size在循环中代替nums.size() 是必须的否则会超时。所以如果采用暴力解法一定要注意代码其他地方的简洁,否则很容易超时。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int size = nums.size(), res = 0;
        for (int i = 0; i < size; ++i) {
            int sum = 0;
            for (int j = i; j < size; ++j) {
                sum += nums[j];
                res += sum == k ? 1 : 0;
            }
        }
        return res;
    }
};

方法二:哈希
考虑如果我们想要一个 O ( n ) O(n) O(n)的算法,那么只能将数组遍历常数次,如果只遍历一次我们只能求得数组的前 i i i项和,如果我们假设 p r e [ i ] pre[i] pre[i]就表示数组的前 i i i项和,那么我们如何表示数组的任意一个子序列 [ i , j ] [i, j] [i,j]的和呢?稍加思考可以发现 p r e [ i ] − p r e [ j − 1 ] pre[i]-pre[j-1] pre[i]pre[j1]正是子序列 [ i , j ] [i,j] [i,j]的和。那么要使子序列的和为 k k k,即 p r e [ i ] − p r e [ j − 1 ] = k pre[i]-pre[j-1] = k pre[i]pre[j1]=k, 通过移项可以得到等价条件 p r e [ i ] − k = p r e [ j − 1 ] pre[i] - k = pre[j-1] pre[i]k=pre[j1],意味着我们只要判断在 i i i之前的前缀中是否存在一个 p r e [ x ] pre[x] pre[x]的值刚好为 p r e [ i ] − k pre[i]-k pre[i]k即可。那么也就意味着我们在进行遍历时需要保存每个 p r e [ i ] pre[i] pre[i]的值, 同时我们需要统计和出现的次数,所以还要保存每个值对应的出现次数,显而易见这里采用map进行存储是最合适的。代码如下:

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> mp;
        mp[0] = 1;
        int tmp = 0;
        int size = nums.size();
        int count = 0;
        for(int i=0; i<size; ++i)
        {
            tmp += nums[i];
            if(mp.find(tmp-k)!=mp.end()) count += mp[tmp-k];
            mp[tmp]++;
        }
        return count;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值