数据结构Advanced
Index
树状数组
树状数组是一种用于维护前缀信息的数据结构
树状数组
C
在物理空间上是连续的;对于数组中的两个位置
C[x], C[y]
,若满足y = x + 2^k
(其中k
表示x
二进制中末尾 0 的个数),则定义C[x], C[y]
为一组父子关系;由以上定义,可知奇数下标的位置一定是叶子节点
C[i] 的直观含义
C[i]
实际上表示原数组中一段区间内的某个统计意义(区间和、区间积、区间最值等等);该区间为
[i-2^k+1, i]
,是一个闭区间;以区间和为例
树状数组的构建(以区间和问题为例)
LeetCode - 307. 区域和检索 - 数组可修改
问题描述
构建树状数组的过程即初始化数组
C
的过程基本操作:
lowbit(x)
——求 2^k,其中 k 表示 x 二进制位中后缀 0 的个数updateC(x, delta)
——更新 C 数组中 A[x] 的祖先如果是初始化阶段 delta = A[i],
如果是更新 A[i],则 delta = new_val - A[i]
sumPrefix(x)
——求前缀区间 [1, x] 的和update(i, val)
——更新 A[i] = val,同时也会更新所有 A[i] 的祖先sumRange(lo, hi)
——求范围 [lo, hi] 的区间和
C++
树状数组的特点
线段树不能解决的问题,树状数组也无法解决;
树状数组和线段树的时间复杂度相同:初始化
O(n)
,查询和修改O(logn)
;但实际效率要高于线段树;直接维护前缀信息也能解决查询问题,但是修改的时间复杂度会比较高;
相关问题
665. 二维区域和检索 - 矩阵不可变 - LintCode
817. 二维区域和检索 - 矩阵可变 - LintCode
249. 统计前面比自己小的数的个数 - LintCode
248. 统计比给定整数小的数的个数 - LintCode
532. 逆序对 - LintCode
相关阅读
夜深人静写算法(三)- 树状数组 - CSDN博客
数据结构设计
LRU 缓存
LeetCode/146. LRU缓存机制
思路
双向链表 + haspmap
数据除了被保存在链表中,同时也保存在 map 中;前者用于记录数据的顺序结构,后者以实现
O(1)
的访问。
更新过程:
新数据插入到链表头部
每当缓存命中(即缓存数据被访问),则将数据移到链表头部
当链表满的时候,将链表尾部的数据丢弃
操作:
put(key, value)
:如果 key 在 hash_map 中存在,则先重置对应的 value 值,然后获取对应的节点,将节点从链表移除,并移动到链表的头部;若果 key 在 hash_map 不存在,则新建一个节点,并将节点放到链表的头部。当 Cache 存满的时候,将链表最后一个节点删除。get(key)
:如果 key 在 hash_map 中存在,则把对应的节点放到链表头部,并返回对应的value值;如果不存在,则返回-1。
C++(AC)
最后更新于