【LeetCode热题100】560. 和为 K 的子数组(子串)

一.题目要求

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

二.题目难度

中等

三.输入样例

示例 1:

输入:nums = [1,1,1], k = 2

输出:2

示例 2:

输入:nums = [1,2,3], k = 3

输出:2

提示:

1 <= nums.length <= 2 ∗ 1 0 4 2 * 10^4 2∗104

-1000 <= nums[i] <= 1000
− 1 0 7 -10^7 −107 <= k <= 1 0 7 10^7 107

四.解题思路

解法1:暴力穷举

解法2:前缀和 + 哈希表

优化思路

前缀和(Prefix Sum):这是一种常用的技巧,可以快速计算任意区间内的元素和。我们遍历数组,计算从第一个元素到当前元素的总和,并将这个总和保存起来作为前缀和。

哈希表(Hash Map):利用哈希表存储不同前缀和出现的次数。这样,对于每一个新的前缀和,我们可以在常数时间内查询哈希表找到之前有多少个前缀和等于当前前缀和减去k。这是因为如果存在一个旧的前缀和等于当前前缀和减去k,那么从那个旧的前缀到当前前缀的子数组和就为k。

五.代码实现

解法1

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {

        int result = 0;
        int tmp;
        //0 1 2 0 -1 2 0  3
        int i, j;
        for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++)
        {
            tmp = 0;
            for (vector<int>::iterator itt = it; itt != nums.end(); itt++)
            {
                tmp += *itt;
                if (tmp == k)
                {
                    result++;
                }
            }
        }

        return result;
    }
};

解法2

c 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int count = 0, sum = 0;
        unordered_map<int, int> prefixSumCount;
        prefixSumCount[0] = 1;  // 初始化,和为0的前缀和出现一次

        for (int num : nums) {
            sum += num;  // 计算当前前缀和
            // 检查是否存在一个旧的前缀和,使得旧的前缀和与当前前缀和之间的差等于k
            if (prefixSumCount.count(sum - k)) {
                count += prefixSumCount[sum - k];
            }
            // 更新当前前缀和的计数
            prefixSumCount[sum]++;
        }

        return count;
    }
};

六.题目总结

哈希表+前缀和的技术通常用于解决涉及数组或序列累积和的问题,特别是当需要快速查询子数组或子序列和的场合。这种方法特别适用于以下几类问题:

  • 连续子数组的和:最常见的应用是找出数组中和为给定值的连续子数组数量。前缀和可以快速计算任意(i, j]区间的和,而哈希表用来存储各个前缀和出现的次数,从而在O(1)时间内判断是否存在某个特定的前缀和值。
  • 求和等于特定值的子数组数量:如上例所示,通过计算当前前缀和并查询哈希表中是否存在一个或多个前缀和,使得当前前缀和与这些前缀和之差等于目标值,可以快速找到子数组和为特定值的数组数量。
  • 数组的子区间问题:对于求解数组中满足特定条件的子区间(如和为k的子数组)数量问题,可以通过维护一个前缀和的哈希表来优化查找过程,从而避免使用双重循环,实现更高效的算法。
  • 处理多次查询:当面对多次查询数组区间和的问题时,前缀和结合哈希表可以大大减少重复计算,每次查询可以在O(1)时间内完成,特别是当数组不经常变化而查询非常频繁时。
  • 寻找具有特定和的子矩阵:在二维数组(如矩阵)中,前缀和技术可以扩展到二维,用于快速计算任意子矩阵的和,结合哈希表可以用来解决特定和的子矩阵问题。

使用哈希表加前缀和的方法,可以将一些原本时间复杂度较高的问题转化为线性时间复杂度处理,从而大幅提升算法效率。这种方法的关键优势在于它通过空间换时间,利用哈希表来快速访问和更新前缀和信息,避免了冗余的计算和遍历。

相关推荐
末央&3 分钟前
【数据结构】手撕AVL树(万字详解)
数据结构·c++
序属秋秋秋4 分钟前
《数据结构初阶》【二叉树 精选9道OJ练习】
c语言·数据结构·c++·算法·leetcode
Tiny番茄6 分钟前
LeetCode 235. 二叉搜索树的最近公共祖先 LeetCode 701.二叉搜索树中的插入操作 LeetCode 450.删除二叉搜索树中的节点
数据结构·算法·leetcode
S01d13r7 小时前
LeetCode 解题思路 48(编辑距离、只出现一次的数字)
算法·leetcode·职场和发展
C_Liu_7 小时前
C语言:深入理解指针(5)
java·c语言·算法
small_wh1te_coder7 小时前
从经典力扣题发掘DFS与记忆化搜索的本质 -从矩阵最长递增路径入手 一步步探究dfs思维优化与编程深度思考
c语言·数据结构·c++·stm32·算法·leetcode·深度优先
枫景Maple7 小时前
LeetCode 45. 跳跃游戏 II(中等)
算法·leetcode
এ᭄画画的北北7 小时前
力扣-236.二叉树的最近公共祖先
算法·leetcode
z人间防沉迷k8 小时前
堆(Heap)
开发语言·数据结构·笔记·python·算法
hy.z_7778 小时前
【数据结构】链表 LinkedList
java·数据结构·链表