从零学算法560

这篇具有很好参考价值的文章主要介绍了从零学算法560。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

560. 和为 K 的子数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2文章来源地址https://www.toymoban.com/news/detail-618187.html

  • 比较容易想到的是暴力解法(我承认我想不到)。为了不遗漏的得到每个连续子数组的和,即为了得到所有 nums 中下标范围为 i~j 的区间的和(0<i<=j<nums.length ),直接双重遍历即可。
  •   public int subarraySum(int[] nums, int k) {
          int count = 0;
          // i 为起点,遍历 j 时得到以 i 为起点的每个连续子数组的和
          // i 遍历了整个数组也就是说每个点作为起点的连续子数组都试过了,所以没有遗漏的情况
          // 比如 nums 为 [1,2,3]
          // sum 尝试了 1,1+2,1+2+3
          // 然后尝试了 2,2+3
          // 最后尝试了 3(我还是不理解我为什么想不到暴力解法)
          for (int i = 0; i < nums.length; i++) {
              int sum = 0;
              for (int j = i; j< nums.length; j++) {
                  sum += nums[j];
                  if (sum == k) {
                      count++;
                  }
              }
          }
          return count;
      }
    
  • 使用前缀和+哈希表优化,前缀和的思想其实早就学过。比如数列前两项的和 S2 为 n1+n2,前四项的和 S4 为 n1+n2+n3+n4,如果问你 n3+n4 为多少,你可以发现就是 S4-S2,即 ni+…nj = Si-S(j-1)。
  • 前缀和就是用一个数组 s,s[n] 保存了数组 nums 前 n-1 位的和,比如 nums 为 [1,2,3],s[3] 保存了 nums 的前两位的和即为 1+2=3。如果让你求 s[4] 你只需要 s[3] + nums[2] 即可。插一嘴得到前缀和数组的公式:
  •   int[] s = new int[nums.length+1];
      // 正常来说应该是 s[i] = s[i-1] + nums[i] 
      // 但是数组下标从 0 开始
      for(int i=0;i<nums.length;i++){
      	s[i+1] = s[i]+nums[i]
      }
    
  • 首先再解读一下题目,题目要求可以理解为 ni+…+nj = k ,这样的 i 和 j 有几对?。而暴力解法的短处在于,先遍历 i 视为当前 i 已确定,此时再加一重遍历,视为 j 也确定,然后遍历 j 时就能不断得到 ni+..+nj, ni+...+n(j+1)...,然后统计遍历过程中有几个和等于 k 即可。但是现在有了前缀和数组,就当做数列和 S 好了,你会发现,既然我们要求 ni+…+nj,那么遍历前缀和数组时,其实就相当于确定了 j,也就是说此时我们得到的是 Sj,而 k = ni+..+nj = Sj - S(i-1) 也就是说只要存在 S(i-1) = Sj - k,那么这样的 i 有几个就表示 ni+…+nj = k 这样的 i 和 j 有几对,或者说当 j 确定时,也就是 Sj 确定时,等于 Sj - k 的前缀和有几个就表示 ni+…+nj = k 这样的 i 和 j 有几对。(比如当前前缀和为 5,k 为 2,那 5 前面有几个前缀和等于 3 就表示我能得到几个 2 了,反证一下,比如 n1+n2+n3+n4 = 5, n1+n2 = 3,那么就有 n3+n4 这样的连续和为 2)为了记录某个前缀和有几对,我们自然很容易想到用哈希表。
  •   public int subarraySum(int[] nums, int k) {
          if (nums.length == 0) {
              return 0;
          }
          // key:前缀和,value:出现次数
          HashMap<Integer,Integer> map = new HashMap<>();
          //细节,这里需要预存前缀和为 0 的情况,否则会漏掉前几位就满足的情况
          // 也就是会漏掉 Sj=k ,即 n1+..+nj 恰好等于 k 的情况
          // 因为这样的 n1+..+nj 虽然等于 k 但是没有 S0 给你减,那么我们就默认 n0=0,S0=0,
          // 减个 0 就不会对你的结果有任何影响了,所以需要map.put(0,1),垫下底
          map.put(0, 1);
          int count = 0;
          int presum = 0;
          // 既然是不断确定 Sj 然后往前找有几个对应的 S(i-1),那么没必要先求出前缀和数组再遍历
          // 更新 presum 的过程实际上就是遍历前缀和数组确定 j 的过程
          for (int x : nums) {
              presum += x;
              // 当前前缀和已知,判断是否含有 presum - k的前缀和,那么我们就知道某一区间的和为 k 了。
              // 比如 i 为 4,当前前缀和 S4 为 n1+n2+n3+n4 = presum ,如果有一个前缀和为 presum - k,
              // 比如 S2 和为 presum - k,即 n1+n2 = presum - k,那么 S4-S2 = presum - (presum - k) = k ,
              // 也就是说存在区间为 n3+n4 = k
              if (map.containsKey(presum - k)) {
                  count += map.get(presum - k);//获取次数
              }
              //更新
              map.put(presum,map.getOrDefault(presum,0) + 1);
          }
          return count;
      }
    
    

到了这里,关于从零学算法560的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零学算法154

    154 .已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4] 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7] 注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为

    2024年02月13日
    浏览(34)
  • 从零学算法55

    55 .给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1: 输入:nums = [2,3,1,1,4] 输出:true 解释:可以先跳 1 步,从下标

    2024年02月21日
    浏览(55)
  • 从零学算法34

    34 .给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示例 1: 输入:nums = [5,7,7,8,8,10], target

    2024年02月13日
    浏览(38)
  • 从零学算法113

    113 .给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1: 输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:[[5,4,11,2],[5,8,4,5]] 示例 2: 输入:root = [1,2,3]

    2024年02月11日
    浏览(35)
  • 从零学算法

    1575.给你一个 互不相同 的整数数组,其中 locations[i] 表示第 i 个城市的位置。同时给你 start,finish 和 fuel 分别表示出发城市、目的地城市和你初始拥有的汽油总量 每一步中,如果你在城市 i ,你可以选择任意一个城市 j ,满足 j != i 且 0 = j locations.length ,并移动到城市 j 。从

    2024年02月06日
    浏览(25)
  • 从零学算法78

    78 .给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 示例 2: 输入:nums = [0] 输出:[[],[0]] 如果将该题想象

    2024年01月19日
    浏览(36)
  • 从零学算法(LCR 180)

    文件组合 .待传输文件被切分成多个部分,按照原排列顺序,每部分文件编号均为一个 正整数(至少含有两个文件)。传输要求为:连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组合列表。 注意,返回时需遵循以下规则: 每种组合

    2024年02月07日
    浏览(31)
  • 从零学算法(剑指 Offer 45)

    输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 示例 1: 输入: [10,2] 输出: “102” 示例 2: 输入: [3,30,34,5,9] 输出: “3033459” 我的原始人解法:直接冒泡排序,把最先应该拼接的那个数不断后移,然后拼接即可。关键就

    2024年02月10日
    浏览(36)
  • 从零学算法 (剑指 Offer 13)

    地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+

    2024年02月11日
    浏览(32)
  • unity的学习,准备搞一款mmo小游戏,服务器和客户端从零学

    先学一下unity,mmo服务器框架到时候在学习一下,暂时服务器简单做一下 如代码所示,简单了解一下。 我个人感觉不要一个放在Awake函数中,一个放在Start中。因为这只适合两个脚本使用,如果多个脚本还是没有办法解决脚本执行的顺序。在这里设置脚本的执行顺序,添加进

    2023年04月21日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包