刷题-快照数组

Huan Lee Lv5

题目描述

实现支持下列接口的「快照数组」- SnapshotArray:

SnapshotArray(int length) - 初始化一个与指定长度相等的 类数组 的数据结构。初始时,每个元素都等于 0。
void set(index, val) - 会将指定索引 index 处的元素设置为 val。
int snap() - 获取该数组的快照,并返回快照的编号 snap_id(快照号是调用 snap() 的总次数减去 1)。
int get(index, snap_id) - 根据指定的 snap_id 选择快照,并返回该快照指定索引 index 的值。

示例:

1
2
3
4
5
6
7
8
9
输入:["SnapshotArray","set","snap","set","get"]
[[3],[0,5],[],[0,6],[0,0]]
输出:[null,null,0,null,5]
解释:
SnapshotArray snapshotArr = new SnapshotArray(3); // 初始化一个长度为 3 的快照数组
snapshotArr.set(0,5); // 令 array[0] = 5
snapshotArr.snap(); // 获取快照,返回 snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0); // 获取 snap_id = 0 的快照中 array[0] 的值,返回 5

分析

最开始没有理解快照数组的意思, 所以做错了几次. 快照是指对某个阶段的数据进行备份, 并不影响数据的修改是连续的.

  • 暴力解法, 将每次快照都进行完整备份: vector<int, vector<int>>, 会爆内存.
  • 把粒度变细, 对每个index内发生的变化进行记录: vector<map<int, int>>

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SnapshotArray {
private:
// vector for each index
// map <snapTime, val>
vector<map<int, int>> snapshots;
int snapTime = 0;

public:
SnapshotArray(int length) {
snapshots = vector<map<int, int>>(length, map<int, int>());
}

void set(int index, int val) { snapshots[index][snapTime] = val; }

int snap() { return snapTime++; }

int get(int index, int snap_id) {
auto it = snapshots[index].upper_bound(snap_id);
return it == snapshots[index].begin() ? 0 : (--it)->second;
}
};

可优化的部分

  • snapshots = vector<map<int, int>>(length, map<int, int>()); 这条初始化很消耗时间和内存, 会生成很多没必要的index slot, 考虑到测试用例的规模可以转换成unordered_map(hashmap)
  • snapTime是递增的, 因此可以用vector<pair<int, int>>加上二分查找来代替map. (这个预计收益不大)
  • Title: 刷题-快照数组
  • Author: Huan Lee
  • Created at : 2023-08-28 14:19:14
  • Updated at : 2024-02-26 04:53:15
  • Link: https://www.mirthfullee.com/2023/08/28/刷题-快照数组/
  • License: This work is licensed under CC BY-NC-SA 4.0.
On this page
刷题-快照数组