Snapshot Array

medium design binary search

Problem

Design an array of length n initialized to 0, with operations: set(index, val), snap() returning a snap_id, and get(index, snap_id) returning the value at that index when snap_id was taken.

InputSnapshotArray(3); set(0,5); snap(); set(0,6); get(0,0)
Output5
snap 0 captured index 0 = 5; later writes don't change snap 0.

from bisect import bisect_right
class SnapshotArray:
    def __init__(self, length):
        self.snap_id = 0
        self.h = [[(-1, 0)] for _ in range(length)]
    def set(self, index, val):
        self.h[index].append((self.snap_id, val))
    def snap(self):
        self.snap_id += 1
        return self.snap_id - 1
    def get(self, index, snap_id):
        col = self.h[index]
        i = bisect_right(col, (snap_id, float('inf'))) - 1
        return col[i][1]
class SnapshotArray {
  constructor(length) {
    this.snapId = 0;
    this.h = Array.from({length}, () => [[-1, 0]]);
  }
  set(index, val) {
    this.h[index].push([this.snapId, val]);
  }
  snap() { return this.snapId++; }
  get(index, snapId) {
    const col = this.h[index];
    let lo = 0, hi = col.length - 1, ans = 0;
    while (lo <= hi) {
      const m = (lo + hi) >> 1;
      if (col[m][0] <= snapId) { ans = col[m][1]; lo = m + 1; }
      else hi = m - 1;
    }
    return ans;
  }
}
class SnapshotArray {
    int snapId = 0;
    List<List<int[]>> h;
    public SnapshotArray(int length) {
        h = new ArrayList<>();
        for (int i = 0; i < length; i++) { List<int[]> col = new ArrayList<>(); col.add(new int[]{-1, 0}); h.add(col); }
    }
    public void set(int index, int val) { h.get(index).add(new int[]{snapId, val}); }
    public int snap() { return snapId++; }
    public int get(int index, int snapId) {
        List<int[]> col = h.get(index);
        int lo = 0, hi = col.size() - 1, ans = 0;
        while (lo <= hi) {
            int m = (lo + hi) >>> 1;
            if (col.get(m)[0] <= snapId) { ans = col.get(m)[1]; lo = m + 1; } else hi = m - 1;
        }
        return ans;
    }
}
class SnapshotArray {
public:
    int snapId = 0;
    vector<vector<pair<int,int>>> h;
    SnapshotArray(int length) : h(length, {{-1, 0}}) {}
    void set(int index, int val) { h[index].push_back({snapId, val}); }
    int snap() { return snapId++; }
    int get(int index, int sid) {
        auto& col = h[index];
        int lo = 0, hi = (int)col.size() - 1, ans = 0;
        while (lo <= hi) {
            int m = (lo + hi) / 2;
            if (col[m].first <= sid) { ans = col[m].second; lo = m + 1; }
            else hi = m - 1;
        }
        return ans;
    }
};
Time: O(log Q) per get Space: O(n + Q)