Snapshot Array

Versioned array with O(1) snap and O(log s) lookup — store change history per index, binary search by snap id.

Medium
Time O(log s) per get Space O(s + writes)
LeetCode
5 min read
design binary-search versioning

Problem#

Implement an array of length n supporting set(idx, val), snap() (returns the current snap id and increments it), and get(idx, snap_id) returning the value at that index at that snap.

Examples#

  • init(3); set(0,5); snap(); set(0,6); get(0,0)5
  • snap() then get(idx, snap_id) returns the latest write at or before snap_id.

Constraints#

  • 1 <= length <= 5*10^4, up to 5*10^4 calls.

Approach#

Per index, keep a sorted vector of (snap_id, value). set overwrites the last entry if its snap id matches the current; else appends. get binary-searches the snap id and returns the value just at-or-before.

Solution#

Snapshot Array
class SnapshotArray {
int snapId = 0;
vector<vector<pair<int,int>>> data; // data[i] = sorted list of (snapId, val)
public:
SnapshotArray(int length) : data(length, vector<pair<int,int>>{{0, 0}}) {}
void set(int index, int val) {
auto& v = data[index];
if (v.back().first == snapId) v.back().second = val;
else v.push_back({snapId, val});
}
int snap() { return snapId++; }
int get(int index, int snap_id) {
auto& v = data[index];
int lo = 0, hi = (int)v.size() - 1, ans = 0;
while (lo <= hi) {
int m = (lo + hi) / 2;
if (v[m].first <= snap_id) { ans = m; lo = m + 1; }
else hi = m - 1;
}
return v[ans].second;
}
};

Editorial#

Storing only change events keeps total space proportional to the number of writes, not n * snaps. The binary search returns the largest snap_id at or below the query — that’s the value that was visible when the snapshot was taken.

Complexity#

  • Time: O(1) set/snap amortized, O(log s) get.
  • Space: O(length + writes).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.