和为K的子数组

本文探讨了LeetCode上一道经典题目:给定一个整数数组和一个整数k,寻找数组中和为k的连续子数组的个数。通过对比不同算法,包括暴力循环、使用字典优化的解决方案,最终提供了一种高效的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

示例 1 :

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

说明 :

  1. 数组的长度为 [1, 20,000]。
  2. 数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。

首先想到的思路是在暴力循环的基础上保存累加的中间计算结果,python3代码如下:

 class Solution:
    def subarraySum(self, nums, k):
        sum_list = [nums[0]]
        for i in range(len(nums) - 1):
            sum_list.append(sum_list[i]+nums[i+1])
        res = 0
        for i in range(len(sum_list)):
            sumi = sum_list[i]
            if sumi == k:
                res += 1
            for j in range(i):
                if sumi-sum_list[j] == k:
                    res+=1
        return res

提交发现超时,对应的C++代码可以通过测试:

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

比较快的算法是将列表换成字典来保存之前的计算结果,而不必两层循环,python3代码如下:

class Solution:
    def subarraySum(self, nums, k):
        res = 0
        sum_list = []
        sum_dict = dict({(0,1)})
        for i in range(len(nums)):
            if i == 0:
                sumi = nums[i]
            else:
                sumi = sum_list[i-1]+nums[i]
            sum_list.append(sumi)
            ksub = sumi - k
            num = sum_dict.get(ksub)
            if not num is None:
                res += num
            num = sum_dict.get(sumi)
            if  not num is None:
                sum_dict[sumi] = num+1
            else:
                sum_dict[sumi] = 1
        return (res)
### 为k的连续子数组问题 对于为k的连续子数组问题,可以通过前缀与哈希表相结合的方法高效解决。这种方法的核心思想在于利用前缀的概念减少重复计算,并借助哈希表存储中间结果以加速查询过程。 #### 前缀概念 前缀是一种用于快速计算区间的技术。定义 `prefix_sum[i]` 表示从数组起始位置到第i个元素之间的累计,则任意子数组 `[j, i]` 的可通过如下公式得到: \[ \text{subarray\_sum[j:i]} = \text{prefix_sum[i]} - \text{prefix_sum[j-1]} \] 如果存在某个索引 \( j \),使得 \( prefix\_sum[i] - prefix\_sum[j-1] = k \),那么我们找到了一个满足条件的子数组[^3]。 #### 使用哈希表优化查找 为了进一步提高效率,在遍历过程中维护一个哈希表记录已经遇到过的前缀及其出现次数。当处理当前元素时,检查是否存在 \( prefix\_sum[i] - k \) 已经存在于哈希表中;如果有,则表示之前某些位置上的前缀加上当前位置之后的部分正好构成目标值k的一个有效子数组组合[^5]。 以下是基于上述原理的具体Python实现: ```python def subarraySum(nums, k): count = 0 sums = 0 d = {0: 1} # 初始化字典,键为前缀,值为其出现次数 for num in nums: sums += num if (sums - k) in d: count += d[sums - k] if sums not in d: d[sums] = 0 d[sums] += 1 return count ``` 此函数接收两个参数:一个是整数列表nums代表待分析的数据序列;另一个是整数值k作为期望达到的目标总。它会返回符合条件的不同子数组数目[^4]。 ### 结论 通过采用前缀配合哈希表的方式能够有效地降低时间复杂度至线性级别(O(n)),从而解决了传统暴力枚举方法所带来的性能瓶颈问题[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值