Snapshot Array - Problem
Design and implement a SnapshotArray that efficiently stores historical versions of an array. Imagine building a version control system for an array where you can take snapshots and later retrieve values from any previous snapshot.

Your SnapshotArray class must support:
SnapshotArray(int length) - Initialize array with given length, all elements start as 0
set(index, val) - Update element at given index to val
snap() - Take a snapshot and return snapshot ID (starting from 0)
get(index, snap_id) - Retrieve value at index from a specific snapshot

The key challenge: How do you efficiently store snapshots without using excessive memory when only a few elements change between snapshots?

Input & Output

example_1.py — Basic Operations
$ Input: ["SnapshotArray","set","snap","set","get"] [[3],[0,5],[],[0,6],[0,0]]
Output: [null,null,0,null,5]
💡 Note: Initialize array of length 3: [0,0,0]. Set index 0 to 5: [5,0,0]. Take snapshot 0. Set index 0 to 6: [6,0,0]. Get value at index 0 from snapshot 0, which returns 5 (the value before the second set operation).
example_2.py — Multiple Snapshots
$ Input: ["SnapshotArray","set","snap","set","snap","get","get"] [[2],[1,10],[],[1,20],[],[1,0],[1,1]]
Output: [null,null,0,null,1,10,20]
💡 Note: Initialize array [0,0]. Set index 1 to 10: [0,10]. Snapshot 0. Set index 1 to 20: [0,20]. Snapshot 1. get(1,0) returns 10, get(1,1) returns 20.
example_3.py — No Changes Edge Case
$ Input: ["SnapshotArray","snap","get","get"] [[4],[],[0,0],[2,0]]
Output: [null,0,0,0]
💡 Note: Initialize array [0,0,0,0]. Take snapshot 0 immediately. Both get(0,0) and get(2,0) return 0 since no values were changed from the initial state.

Constraints

  • 1 ≤ length ≤ 5 × 104
  • 0 ≤ index < length
  • 0 ≤ val ≤ 109
  • 0 ≤ snap_id < (number of times snap() is called)
  • At most 5 × 104 calls will be made to set, snap, and get

Visualization

Tap to expand
SnapshotArray: Git for ArraysIndex 0 Timeline:(0,0)Initial(1,5)set(0,5)(3,9)set(0,9)Index 1 Timeline:(0,0)Initial(2,7)set(1,7)Binary Search Queryget(0, 2) - Find value at snap 2Search timeline: (0,0) → (1,5) → (3,9)Largest snap_id ≤ 2 is (1,5)Result: 5Space Efficiency✅ Only store changes, not full arrays✅ Memory: O(changes) vs O(length×snaps)✅ Fast operations: O(1) set/snap, O(log k) getSnapshots:Snap 0Snap 1Snap 2Snap 3Just counters, no data!
Understanding the Visualization
1
Initialize
Each array index maintains its own timeline starting with snapshot 0, value 0
2
Track Changes
When set() is called, append the change to that index's timeline
3
Snapshot
Increment snapshot counter - no copying needed!
4
Retrieve
Binary search the timeline to find the latest change at or before target snapshot
Key Takeaway
🎯 Key Insight: By storing only the changes (like Git diffs) and using binary search to find historical values, we achieve optimal space efficiency while maintaining fast query performance. This is a classic example of trading a small amount of query time complexity for massive space savings.
Asked in
Google 45 Amazon 38 Microsoft 32 Meta 28
42.0K Views
Medium-High Frequency
~25 min Avg. Time
1.4K Likes
Ln 1, Col 1
Smart Actions
💡 Explanation
AI Ready
💡 Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen