关于区间查询和修改问题,开源一下我的四个板子,根据不同的复杂度,适用于不同的场景。
- 其中,所有的板子都封装成一个类,开箱即用;
- 在性能上,如树状数组不必手敲的C-like数组板子效率高,但好就好在拿来就用不需要考虑变量名啥的,并且API尽量做到统一。
下文中的区间都是指双闭区间,且区间和数组的下标起始索引相同,即从0起。如对于数组
[5,1,8,6]
,则区间[2~3]对应[8,6]
。
为了行文简洁,此文仅对核心API进行展示,不对算法进行讲解。
完整代码请到@gist查看。
1. 前缀和
前缀和广泛用于区间和查询的任务里;对一个n
长的数组的所有区间进行查询的复杂度为O(n^2)
,如有必要请使用hashmap改装。
class PreSum: # 标准前缀和模板
def __init__(self, data): # data是原数组
pass
def query(self, i, j): # 查询的是双闭区间[i, j]的区间和
pass
2.差分数组
差分数组广泛用于区间修改,如力扣1109题、1589题。
class Diff: # 通用加减类的差分数组模板
def __init__(self, arr):
pass
def modify(self, i: int, j: int, value): # 取[i~j]的双闭区间进行区间修改
pass
def recover(self): # 复原修改后的数组
pass
由于差分数组适合【多修改、单查询】的场景,因此【多修改、多查询】需要结合前缀和和差分数组,也就是使用树状数组来解决。
3. 树状数组
class BinIndexTree:
def __init__(self