目录
一、题目
1、题目描述
实现支持下列接口的「快照数组」- 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
的值。
2、接口描述
python3
class SnapshotArray:
def __init__(self, length: int):
def set(self, index: int, val: int) -> None:
def snap(self) -> int:
def get(self, index: int, snap_id: int) -> int:
# Your SnapshotArray object will be instantiated and called as such:
# obj = SnapshotArray(length)
# obj.set(index,val)
# param_2 = obj.snap()
# param_3 = obj.get(index,snap_id)
cpp
class SnapshotArray {
public:
SnapshotArray(int length) {
}
void set(int index, int val) {
}
int snap() {
}
int get(int index, int snap_id) {
}
};
/**
* Your SnapshotArray object will be instantiated and called as such:
* SnapshotArray* obj = new SnapshotArray(length);
* obj->set(index,val);
* int param_2 = obj->snap();
* int param_3 = obj->get(index,snap_id);
*/
3、原题链接
二、解题报告
1、思路分析
emmm,熟悉虚拟机对快照并不陌生
快照的id按时间升序,具有单调性,我们没必要每次开一个新的数组,如果想装逼可以用主席树
我们开一个二维数组,每个一维数组末尾放的都是当前索引的最新值以及其快照id
我们查的时候二分查找即可,改的时候如果是当前快照id就直接改,否则添加
2、复杂度
时间复杂度: 查询快照为O(q),q为打快照次数 空间复杂度:O(length + q)
3、代码详解
python3
class SnapshotArray:
def __init__(self, length: int):
self.cur = 0
self.v = [[(0, 0)] for _ in range(length)]
def set(self, index: int, val: int) -> None:
if self.v[index][-1][0] != self.cur:
self.v[index].append((self.cur, val))
else:
self.v[index][-1] = (self.cur, val)
def snap(self) -> int:
self.cur += 1
return self.cur - 1
def get(self, index: int, snap_id: int) -> int:
it = bisect_left(self.v[index], (snap_id + 1, )) - 1
return self.v[index][it][1]
# Your SnapshotArray object will be instantiated and called as such:
# obj = SnapshotArray(length)
# obj.set(index,val)
# param_2 = obj.snap()
# param_3 = obj.get(index,snap_id)
cpp
class SnapshotArray {
typedef pair<int, int> PII;
#define mkp make_pair
vector<vector<PII>> v;
int cur = 0;
public:
SnapshotArray(int length) : v(length, vector<PII>(1, mkp(0, 0))) {
}
void set(int index, int val) {
if (v[index].back().first != cur)
v[index].emplace_back(cur, val);
else
v[index][v[index].size() - 1].second = val;
}
int snap() {
return cur ++;
}
int get(int index, int snap_id) {
auto it = lower_bound(v[index].begin(), v[index].end(), mkp(snap_id, -1));
if(it == v[index].end() || it->first > snap_id) -- it;
return it->second;
}
};
/**
* Your SnapshotArray object will be instantiated and called as such:
* SnapshotArray* obj = new SnapshotArray(length);
* obj->set(index,val);
* int param_2 = obj->snap();
* int param_3 = obj->get(index,snap_id);
*/