「数据结构与算法」动静布局学习笔记:前缀和

前缀和是一种查问数组中任意区间的元素的和的数据结构,这里数组给定之后就不变了。针对这个不变的数组,前缀和用于屡次查问区间 [i, j] 上元素的和。

对于动静布局而言,前缀和的意义次要有两点:

  • 一维和二维前缀和的推导,别离用到了单串和矩阵中最经典的状态设计以及状态转移
  • 在一些更简单的动静布局问题中,状态转移的时候须要依赖区间和,因为状态转移是十分频繁的操作,因而必须高效地求区间和能力使得状态转移的工夫复杂度可承受,此时就必须用到前缀和了

一些问题须要前缀和与其它数据结构配合来解决,也有两类:

  • 先预处理出前缀和数组,这一步是动静布局,而后在前缀和数组上用其它数据结构解决
  • 还是依照动静布局的形式求前缀和,也须要额定的数据结构保护前缀和,但不是预处理好前缀和数组之后再用数据结构计算,而是每求出一个前缀和,就更新一次数据结构并保护答案

前缀和 简介

给定长度 n 的序列 a (a[0], a[1], ..., a[n-1]) ,给每个前缀求一次和, S[0] = 0 , S[i] = a[0] + a[1] + ... + a[i - 1] 。这些前缀和保护在一个长度 n + 1 数组 S 里,称为前缀和数组

有两类在数组 a 上的求和需要:

  1. 前缀和:求 a[0..i] 的和
  2. 区间和:求区间 a[L, R] 的和

对于第 1 种前缀和 S[i + 1] 刚好就是答案,因为这就是前缀和的定义。 S[i+1] = a[0] + a[1] + ... + a[i]

对于第 2 种区间和,如果曾经有了前缀和数组,两个前缀和 S[R + 1] S[L] 的差刚好就是 [L, R] 上的区间和。已有前缀和数组之后,这一步操作就是 O(1) 的。

定义 sums[k] [0..k-1] 的和,其中 sums[0] 示意数组中没有数字被选中, sums[1] 示意只选中第一个数 nums[0]。 事后计算 0 ~ k (0<=k<=n-1) 的和,这一系列的和都是从 0 开始的,因而称为前缀和。公式如下:

  1. k = 0: sum(0, 0) = 0
  2. 1 <= k <= n: sum(0, k) = nums[0] + nums[1] + ... + nums[k - 1]

尔后的区间查问都能够利用公式:

  • sum(i, j) = sums(0, j + 1) - sum(0, i)

线性动静布局中最根底的一种是单串 dp[i] ,并且只与子问题 i - 1 无关,即 dp[i] = f(dp[i-1]) 前缀和就是这种状况, sums[i] 只与 sums[i-1] 无关。推导前缀和数组的过程是 O(N) 的,如果区间和的查问次数达到了 O(N) 那么计算区间和的工夫复杂度是摊销 O(1) 的。

数据结构 保护 前缀和

用动静布局的形式推 sums[i] 的时候,在某些题型中计算完 sums[i] 后须要查问以前算过的后果以此来计算某种指标(例如小于、大于、等于某个数值等),此时就须要用数据结构来将后面的计算结果保护起来,以便高效查问。

前缀和保护在数据结构中,以便于后续的屡次查问,最常见的是保护在哈希表 HashMap中。

HashMap 保护 前缀和Key:前缀和(状态)的值Value:第一次呈现时的索引

经典问题① a[0], a[1], ..., a[n - 1] 上有没有一个区间,其和为 target

关键词:[有没有][区间][等于]

计算前缀和数组 sums[i] 。当扫描到 i 时, a[0], a[1], ..., a[i - 1] 的前缀和都曾经求过了,所以能够在计算的过程中,将前缀和保护在数据结构中,以便于后续的屡次查问。本题在之后要查问前缀和的值是否存在,因而保护在HashSet里。

求完以后值 a[i] 对应的前缀和 S[i+1] , 在插入到HashSet之前先思考: S[i+1] - target HashSet中是否呈现过。

  • 如果呈现:阐明存在以 i 结尾的某个区间,和为 target ,则找到答案
  • 如果不呈现:阐明不存在以 i 结尾的区间,和为 target ,则持续枚举 i + 1

经典问题② a[0], a[1], ..., a[n - 1] 上有多少个区间,其和为 target

关键词:[多少个][区间][等于]

整体解题思路与问题①类似。

区别在于题目要求统计个数,所以须要应用HashMap来代替HashSet并以此保护多个 Key(和的值) - Value(该和的值呈现的个数) 键值对。

LeetCode 560 和为 K 的子数组
https://leetcode-cn.com/probl...

经典问题③ a[0], a[1], ..., a[n - 1] 上有多少个区间,其和大于、小于 target

关键词:[多少个][区间][大于、小于]

LeetCode 327 区间和的个数
https://leetcode-cn.com/probl...

经典问题④ 一棵树上有没有一个门路,其和为 target

关键词:[有没有][树][等于]

LeetCode 437 门路总和 III
https://leetcode-cn.com/probl...

经典问题⑤ 矩形区域内有多少个子矩阵,其和大于、小于或等于 target

关键词:[有没有][多少个][矩形区域][大于、等于、小于]

LeetCode 363 矩形区域不超过 K 的最大数值和
https://leetcode-cn.com/probl...

LeetCode 1074 元素和为目标值的子矩阵数量
https://leetcode-cn.com/probl...

面试题 17.24 最大子矩阵
https://leetcode-cn.com/probl...

对于矩阵问题,能够优先思考将二维矩阵压缩成一维数组,而后参考问题①②③的形式应用前缀和进行求解。