查找总和等于“k”的子数组的数量

2023-12-30

我们将得到一个整数数组和一个值k。我们需要找到总和等于的子数组的总数k.

我在网上(Leetcode)发现了一些有趣的代码,如下:

public class Solution {
    public int subarraySum(int[] nums, int k) {
        int sum = 0, result = 0;
        Map<Integer, Integer> preSum = new HashMap<>();
        preSum.put(0, 1);

        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (preSum.containsKey(sum - k)) {
                result += preSum.get(sum - k);
            }
            preSum.put(sum, preSum.getOrDefault(sum, 0) + 1);
        }

        return result;
    }
}

为了理解它,我浏览了一些具体的例子,比如[1,1,1,1,1] with k=3 and [1,2,3,0,3,2,6] with k=6。虽然代码在这两种情况下都能完美运行,但我无法理解它实际如何计算输出。

我有两个具体的困惑点:

1)为什么代码不断地添加数组中的值,而不将其清零?例如,如果[1,1,1,1,1] with k=3, once sum=3,我们不需要重置吗sum为零?不重置sum干扰查找后面的子数组?

2)我们不应该简单地做result++当我们找到 sum 的子数组时k?为什么我们要添加preSum.get(sum-k)反而?


让我们先解决您的第一个困惑点:

代码不断对数组求和并且不重置的原因sum是因为我们将总和存入preSum(之前的总数)我们继续。然后,任何时候我们到达某个点sum-k是先前的总和(比如在索引处)i),我们知道总和between index i我们当前的索引正是k.

例如,在下图中i=2,我们当前的指数等于4,我们可以看到,自从9,当前指数的总和减去3,索引处的总和i, is 6, 指标之间的总和2 and 4(含)是6.

思考这个问题的另一种方式是看到丢弃[1,2]从数组(在我们当前的索引4) 给我们一个 sum 的子数组6,出于与上述类似的原因(详见图片)。

使用这种思维方法,我们可以说我们想要从数组的前面丢弃,直到剩下 sum 的子数组k。我们可以通过这样说来做到这一点:对于每个索引,“仅丢弃1,然后丢弃1+2,然后丢弃1+2+3等”(这些数字来自我们的示例),直到我们找到 sum 的子数组k (k=6在我们的例子中)。

这给出了一个完全有效的解决方案,但请注意,我们将在数组的每个索引处执行此操作,从而一遍又一遍地对相同的数字求和。节省计算的一种方法是保存这些总和以供以后使用。更好的是,我们已经将这些相同的数字相加以获得当前的sum,因此我们可以随时保存该总数。

要找到子数组,我们只需查看保存的总和,将它们相减并测试剩下的是否是k。必须减去每个保存的总和有点烦人,所以我们可以使用减法的交换律 https://en.wikipedia.org/wiki/Commutative_property看看如果sum-x=k是真的,sum-k=x也是如此。这样我们就可以看看是否x是一个保存的总和,如果是,就知道我们找到了一个大小为k。哈希映射使查找变得高效。

现在来说说你的第二个困惑点:

大多数时候你是对的,在找到合适的子数组后,我们可以这样做result++。几乎总是,值preSum1, so result+=preSum.get(sum-k)将相当于result+=1, or result++.

唯一不是的时候是preSum.put被称为sum之前已经达到了。我们怎样才能回到sum我们已经有了?唯一的方法是使用负数,这会抵消之前的数字,或者使用零,这根本不会影响总和。

基本上,我们回到了之前的状态sum当子数组的总和等于 0 时。此类子数组的两个示例是[2,-2]或琐碎的事[0]。对于这样的子数组,当我们找到一个稍后的、具有 sum 的相邻子数组时k,我们需要添加超过1 to result因为我们发现了不止一个新子数组,其中一个是零和子数组(sum=k+0)和一个没有它的(sum=k).

这就是原因+1 in the preSum.put以及。每次我们都达到相同的目标sum我们再次发现another零和子数组。对于两个零和子数组,找到一个新的相邻子数组sum=k实际上给出了 3 个子数组:新的子数组 (sum=k),新子数组加上第一个零和 (sum=k+0),以及具有两个零和的原始数据(sum=k+0+0)。此逻辑也适用于更多数量的零和子数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找总和等于“k”的子数组的数量 的相关文章

随机推荐

  • 如何在 Catalyst 中使用 NSSharingService?

    我尝试使用 NSSharingService 添加催化剂应用程序以在 macOS 上共享操作表 但出现错误NSSharingService is unavailable in Mac Catalyst if targetEnvironmen
  • 如何区分共享内存和全局内存的指针?

    在 CUDA 中 给定指针的值或变量的地址 是否有一个内在函数或另一个 API 可以内省指针引用的地址空间 CUDA 头文件sm 20 intrinsics h定义函数 device unsigned int isGlobal const
  • Rails Button_to 未正确设置类

    My code 我想以此结束
  • 显示 18 年前的日期选择器并锁定 ios 中的 ui 日期选择器

    在我的项目中 我需要显示 18 年前的日期选择器 并且需要锁定 80 年前的日期 所以我如何在日期选择器中显示这些日期 任何人都可以帮助我在这里找到 这里添加代码我在日志中打印的代码但我需要在我的日期选择器上显示所以我如何显示 NSCale
  • Rspec 未定义的局部变量或方法 root_path

    我开始使用 Rspec 但是当我运行时bundle exec rspec我收到一个错误 spec requests pages spec rb 20 in block 2 levels in
  • 如何从 /bin 目录中加载所有程序集

    在 Web 应用程序中 我想加载 bin 目录中的所有程序集 由于它可以安装在文件系统中的任何位置 因此我无法保证它存储的特定路径 我想要一个 Assembly 装配对象的 List 好吧 您可以使用以下方法自己将其组合在一起 最初使用类似
  • int 整数实例

    为什么当 Java 进行自动装箱时这是一个编译时错误 我错过了什么吗 int primitiveIntVariable 0 if primitiveIntVariable instanceof Integer I get Inconvert
  • 根据晚于特定日期的多列选择行

    我有以下数据框 import pandas as pd import numpy as np np random seed 0 create an array of 5 dates starting at 2015 02 24 one pe
  • ruby 中的一行可以动态初始化多个变量吗? [复制]

    这个问题在这里已经有答案了 我才写了几个星期的代码 这是我的第一个问题 所以请耐心等待 在 ruby 中 我知道您可以在一行上初始化多个变量 如下所示 a b 1 2 但是 我想知道是否可以在循环中初始化多个变量并生成它们的名称 这是一些伪
  • SVN:XML 格式错误错误

    我正在尝试从远程存储库签出分支 签出多个文件 然后签出失败并出现以下错误 svn E175009 XML 响应包含无效的 XML svn E130003 格式错误的 XML 格式不正确 令牌无效 是什么导致了这个问题 有没有办法修复远程存储
  • 如何查看公共数据集?

    我正在尝试按照 GitHub 网站上的说明查看 GitHub 公共数据集 那里的说明说 添加项目名称 githubarchive 但是在 BigQuery 网站上时 我看不到添加项目的方法 我确信我只是没有正确注册或类似的事情 但我不知道如
  • 检查是否设置了对象属性 - SimpleXML

    我有一些 XML 正在使用 PHP 的 SimpleXML 类 并且 XML 中有一些元素 例如
  • 将自定义视图添加到导航项后,自定义视图始终返回 nil

    下面的代码添加了一个自定义视图navigationItem成功了 但是当尝试访问时customView它总是会回来nil override func viewDidLoad super viewDidLoad let customView
  • os.path.join 和 os.sep 连接的使用差异

    我正在尝试弄清楚使用以下方法是否更好 os path join str1 str2 or str1 os sep str2 分析与timeit我发现 正如预期的那样 串联速度更快 timeit playground os sep Text
  • 从 XPS 文档中提取单个页面

    我需要拆分现有的 XPS 文档并创建一个新的 XPS 文档 其中只有原始文档的一页 我尝试复制文档并从复制的文档中删除页面 但这非常慢 有没有更有效的方法来做到这一点 请使用 C Thanks 解决 public void Split st
  • 中断 D3.js 中的滚动转换

    我正在使用scrollama javascript 库编写一篇 scrolllytelling 文章 其中涉及当用户滚动时将D3 图形移入和移出视图 它大部分工作正常 但如果我滚动太快 图表就会堆积在一起 这是一个jsfiddle http
  • 编译关于缺少 @required 协议方法未出现的警告

    今天早上我正在修改 XCode 4 5 2 想要制作一个表格视图 我自然地添加了UITableViewDataSource and UITableViewDelegate我的视图控制器定义上的协议 import
  • 通过 Linux 终端运行 Java GUI 应用程序

    我在 Ubuntu 上尝试通过终端运行 Java GUI 应用程序 当我尝试运行它时 出现 HeadlessException 下面是堆栈跟踪 Exception in thread AWT EventQueue 0 java awt He
  • 清除本地存储但免除某些值。

    有没有办法清除 window localStorage 即window localStorage clear 但豁免某些键 值对 不 但您可以将所需的值保存在变量中 然后清除localStorage然后再次将存储在变量中的项目添加到其中 E
  • 查找总和等于“k”的子数组的数量

    我们将得到一个整数数组和一个值k 我们需要找到总和等于的子数组的总数k 我在网上 Leetcode 发现了一些有趣的代码 如下 public class Solution public int subarraySum int nums in