ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

算法30,前缀和,和为k的子数组

算法30,前缀和,和为k的子数组 我用一个完全白话的思路给你讲清楚这个算法不跳步 你现在卡住的点主要是两个为什么要用前缀和 哈希表getOrDefault在这里到底干了什么一、先不讲代码先看数学本质假设数组是nums [a, b, c, d]定义sum[i]从下标0到i的所有元素之和叫前缀和例如sum[0] a sum[1] a b sum[2] a b c sum[3] a b c d一个重要结论如果某一段子数组[j1 ... i]的和是k那么一定有sum[i] - sum[j] k换句话说✅只要前面出现过sum - k就能找到一个合法子数组二、用一个具体例子走一遍示例nums [1, 1, 1] k 2遍历到的数当前 sumsum - khash 里有没有贡献子数组数11-1❌0120✅0 出现过1131✅1 出现过1✅ 一共2个子数组[1,1][1,1]三、hash到底存的是什么哈希表存的是某个前缀和出现了多少次key → 前缀和 value → 出现过几次初始时hash.put(0, 1);为什么因为还没遍历数组时前缀和就是0这样可以让[0...i]这种从开头开始的子数组也被算进去四、getOrDefault到底是干嘛的方法签名hash.getOrDefault(key, defaultValue)意思是如果 key 存在 → 返回它的值如果不存在 → 返回 defaultValue在你这段代码里ret hash.getOrDefault(sum - k, 0);等价于if (hash.containsKey(sum - k)) { ret hash.get(sum - k); } else { ret 0; }它的作用一句话总结✅“以前有没有出现过sum - k有的话有几个”每一个出现都对应一个合法子数组。五、再看这一行非常关键hash.put(sum, hash.getOrDefault(sum, 0) 1);意思是当前前缀和sum出现了一次如果之前出现过就次数 1如果没出现过就从 0 开始 1一定要先查再存顺序不能反六、完整流程人话版我从左到右走数组每走一步算一下“到这儿为止的总和”问自己“之前有没有哪个前缀和使得当前总和 - 那个前缀和 k”有几次就有几个子数组把当前总和记下来留给后面用七、为什么这题不能用暴力暴力是枚举所有起点 终点 → O(n²)前缀和 哈希表是只扫一遍 → O(n)八、一句话终极理解 ✅哈希表不是在存“子数组”而是在存“历史账单”​每到一个新位置就问一句“历史上有没有一笔账能跟我现在凑成 k”
返回列表