Skip to content

1146. Snapshot Array 👍

  • Time:
    • Constructor: $O(\texttt{length})$
    • set(index: int, val: int): $O(1)$
    • snap(): $O(1)$
    • get(index: int, snap_id: int): $O(\log |\texttt{set()}|)$
  • Space: $O(|\texttt{set()}|)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class SnapshotArray {
 public:
  SnapshotArray(int length) : snaps(length) {
    for (auto& snap : snaps)
      snap.emplace_back(0, 0);
  }

  void set(int index, int val) {
    auto& [lastSnapId, lastVal] = snaps[index].back();
    if (lastSnapId == snap_id)
      lastVal = val;
    else
      snaps[index].emplace_back(snap_id, val);
  }

  int snap() {
    return snap_id++;
  }

  int get(int index, int snap_id) {
    const vector<pair<int, int>>& snap = snaps[index];
    auto it = ranges::lower_bound(snap, make_pair(snap_id + 1, 0));
    return prev(it)->second;
  }

 private:
  // snaps[i] := [(snap_id, val)]
  vector<vector<pair<int, int>>> snaps;
  int snap_id = 0;
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class SnapshotArray {
  public SnapshotArray(int length) {
    snaps = new List[length];
    for (int i = 0; i < length; ++i) {
      snaps[i] = new ArrayList<>();
      snaps[i].add(new int[] {0, 0});
    }
  }

  public void set(int index, int val) {
    int[] snap = snaps[index].get(snaps[index].size() - 1);
    if (snap[0] == snap_id)
      snap[1] = val;
    else
      snaps[index].add(new int[] {snap_id, val});
  }

  public int snap() {
    return snap_id++;
  }

  public int get(int index, int snap_id) {
    int i = Collections.binarySearch(snaps[index], new int[] {snap_id, 0},
                                     (a, b) -> Integer.compare(a[0], b[0]));
    if (i < 0)
      i = -i - 2;
    return snaps[index].get(i)[1];
  }

  private List<int[]>[] snaps;
  private int snap_id = 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class SnapshotArray:
  def __init__(self, length: int):
    self.snaps = [[[0, 0]] for _ in range(length)]
    self.snap_id = 0

  def set(self, index: int, val: int) -> None:
    snap = self.snaps[index][-1]
    if snap[0] == self.snap_id:
      snap[1] = val
    else:
      self.snaps[index].append([self.snap_id, val])

  def snap(self) -> int:
    self.snap_id += 1
    return self.snap_id - 1

  def get(self, index: int, snap_id: int) -> int:
    i = bisect_left(self.snaps[index], [snap_id + 1]) - 1
    return self.snaps[index][i][1]