leetcode - 1146. Snapshot Array

Description

Implement a SnapshotArray that supports the following interface:

SnapshotArray(int length) initializes an array-like data structure with the given length. Initially, each element equals 0.
void set(index, val) sets the element at the given index to be equal to val.
int snap() takes a snapshot of the array and returns the snap_id: the total number of times we called snap() minus 1.
int get(index, snap_id) returns the value at the given index, at the time we took the snapshot with the given snap_id

Example 1:

Input: ["SnapshotArray","set","snap","set","get"]
[[3],[0,5],[],[0,6],[0,0]]
Output: [null,null,0,null,5]
Explanation: 
SnapshotArray snapshotArr = new SnapshotArray(3); // set the length to be 3
snapshotArr.set(0,5);  // Set array[0] = 5
snapshotArr.snap();  // Take a snapshot, return snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0);  // Get the value of array[0] with snap_id = 0, return 5

Constraints:

1 <= length <= 5 * 10^4
0 <= index < length
0 <= val <= 10^9
0 <= snap_id < (the total number of times we call snap())
At most 5 * 10^4 calls will be made to set, snap, and get.

Solution

Memory Limit Error

Use a HashMap to keep track of every change. Use snap_id as the key, use a list as the value. The list is the current array. Every time the snap function is called, duplicate the previous array to form a new array.
Time complexity: Linear with the time of calling get function
Space complexity: In the worst scenario, it would use 5 ∗ 1 0 4 ∗ 5 ∗ 1 0 4 = 25 ∗ 1 0 8 5*10^4*5*10^4=25*10^8 51045104=25108 space.

Bisect

In the previous solution, we would encounter memory limit error. It was because we keep track of every value in every change, even when most of them are the same. So this time, we need to reduce the space complexity at the cost of time complexity.
Use a list of list to keep track of every index, and only append values when the value at the index was changed. When get function was called, use binary search to find the largest snap_id that is smaller than the snap_id in get function.

Code

Memory Limit Error

class SnapshotArray:

    def __init__(self, length: int):
        self.value = {0: [0] * length}
        self.snap_id = 0

    def set(self, index: int, val: int) -> None:
        self.value[self.snap_id][index] = val

    def snap(self) -> int:
        self.value[self.snap_id + 1] = self.value[self.snap_id].copy()
        self.snap_id += 1
        return self.snap_id - 1

    def get(self, index: int, snap_id: int) -> int:
        return self.value[snap_id][index]
        


# 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)

Binary Search

class SnapshotArray:

    def __init__(self, length: int):
        self.snap_id = 0
        self.value = [[(self.snap_id, 0)] for _ in range(length)]
        
    def set(self, index: int, val: int) -> None:
        self.value[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:
        def find_largest_snap_id(id_value: list, snap_id: int) -> int:
            left, right = 0, len(id_value) - 1
            while left < right:
                mid = (left + right + 1) // 2
                if id_value[mid][0] > snap_id:
                    right = mid - 1
                else:
                    left = mid
            return (left + right + 1) // 2
        # use bisect to find the largest store_snap_id that is smaller than snap_id
        res_index = find_largest_snap_id(self.value[index], snap_id)
        return self.value[index][res_index][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)

你可能感兴趣的:(OJ题目记录,leetcode,数据结构,算法)