当前位置: 首页 > news >正文

和为 K 的子数组-leetcode

题目描述

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

解法一

思路:

枚举算法,从下标i开始,统计后面所有位置的字串和,当中若出现和为k则个数加一

代码:

public class leetcode_010 {public static int subarraySum(int[] nums, int k) {int ans=0;int tempSum=0;for(int i=0;i<nums.length;i++){tempSum+=nums[i];if(tempSum==k)ans++;for (int j=i+1;j<nums.length;j++){tempSum+=nums[j];if(tempSum==k)ans++;}tempSum=0;}return ans;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);String[] line = sc.nextLine().split(",");int[] nums= Arrays.stream(line).mapToInt(Integer::parseInt).toArray();int k = sc.nextInt();int res = subarraySum(nums,k);System.out.println(res);}
}

解法二

思路:

来自官方的解答,采用前缀和和哈希表进行优化,时间复杂度为O(n)。

  • 前缀和(Prefix Sum):定义 pre[i] 为数组从索引 0i 的所有元素之和。例如,对于数组 numspre[i] = nums[0] + nums[1] + ... + nums[i]
  • 子数组和:子数组 [j..i] 的和可以表示为 pre[i] - pre[j-1]。注意,当 j=0 时,pre[j-1] 定义为 0(即没有元素时的前缀和)。
  • 目标条件:我们想找到所有满足 pre[i] - pre[j-1] == k 的子数组。这等价于 pre[j-1] == pre[i] - k。因此,对于每个 i,我们需要统计有多少个 j(其中 j0i)使得 pre[j-1] 等于 pre[i] - k

为了高效地统计这些 j 的个数,我们使用一个哈希表(如 HashMap),键是前缀和的值,值是该前缀和出现的次数。这样,对于每个 i,我们可以直接在哈希表中查找 pre[i] - k 的出现次数,从而避免重复计算。

步骤详解

  1. 初始化
    • 创建一个哈希表 map,用于存储前缀和及其出现次数。
    • 初始时,放入前缀和 0,出现次数为 1。这是因为当没有元素时,前缀和为 0,且这相当于 j=0 时的 pre[j-1] = 0
    • 初始化当前前缀和 pre = 0 和计数器 count = 0
  2. 遍历数组
    • 对于每个元素 nums[i]
      • 更新当前前缀和:pre = pre + nums[i]
      • 计算目标值 target = pre - k。这个目标值就是我们要在哈希表中查找的 pre[j-1]
      • 如果 target 存在于哈希表中,则说明存在若干下标 j(对应 pre[j-1] = target),使得子数组 [j..i] 的和为 k。因此,将 count 加上 map.get(target)
      • 将当前前缀和 pre 加入哈希表:如果 pre 已存在,则将其出现次数加 1;否则,放入 pre 并设置次数为 1
  3. 返回结果
    • 遍历结束后,count 即为所有和为 k 的连续子数组的个数。

遍历的过程中,我们先求出前缀和,当下标来到i时,我们求pre[i]-k出现的次数,即需要统计有多少个 j(其中 j0i)使得 pre[j-1] 等于 pre[i] - k。这些前缀和在我们求pre[i]前就已经求出。

为什么pre[i] - k出现的次数等于多少个j,因为我们从头开始求前缀和,[0i]只会统计一次,当出现相同的前缀和时,是不用的[0i]计算得来的。

代码:

public class Solution {public int subarraySum(int[] nums, int k) {int count = 0, pre = 0;HashMap < Integer, Integer > mp = new HashMap < > ();mp.put(0, 1);for (int i = 0; i < nums.length; i++) {pre += nums[i];if (mp.containsKey(pre - k)) {count += mp.get(pre - k);}mp.put(pre, mp.getOrDefault(pre, 0) + 1);//若当前前缀和不存在,则创建该前缀和,出现次数置为1,若出现过这个前缀和,则该前缀和出现的次数加1}return count;}
}
http://www.wxhsa.cn/company.asp?id=2919

相关文章:

  • 元推理agi不是象人思维,而是教人思维,人类脸上挂不住啊
  • 《10人以下小团队管理手册》读后感
  • GZHOIOJ律(二)
  • 优惠券
  • GZHOIOJ律(一)
  • 基于ArcGIS Pro SDK 3.4.2 + C# + .NET 8 的自动化制图系统初探
  • Kali Linux 虚拟机安装(VMware Workstation 17)
  • 单例模式:线程安全,以及volatile关键字
  • lilctf 部分wp - Elma
  • 用 Python 和 Tesseract 实现验证码识别
  • Java 和 Tesseract 实现验证码识别
  • 基于 Weiler–Atherton 算法的 IoU 求解
  • Selenium应用中的核心JavaScript操作技巧
  • 25.9.13 字符编码标准
  • 哭了,散了,明白了
  • 用 Java 和 Tesseract 实现验证码识别
  • Microsoft-Activation-Scripts,好用,记录一下。
  • 双重map 的赋值初始化
  • 0voice-1.4.1
  • 9.13 模拟赛 T3
  • Docker应用 - FileBrowser
  • AI踩坑之Nlog使用
  • 论文解读-《OpenGSL A Comprehensive Benchmark for Graph Structure Learning》 - zhang
  • Cmake介绍
  • Git 生成 ssh key
  • 基础篇:消息队列理论部分,另一种环境搭建Docker运行RabbitMQ
  • 项目案例作业1:学生信息管理系统(面向对象初步接触)
  • P1097 合唱队形
  • 一生一芯学习:pa2.1 RTFM
  • Linux网络:初识网络 - 详解