LeetCode-Python-1146. 快照数组

636 篇文章 23 订阅

实现支持下列接口的「快照数组」- SnapshotArray:

  • SnapshotArray(int length) - 初始化一个与指定长度相等的 类数组 的数据结构。初始时,每个元素都等于 0
  • void set(index, val) - 会将指定索引 index 处的元素设置为 val
  • int snap() - 获取该数组的快照,并返回快照的编号 snap_id(快照号是调用 snap() 的总次数减去 1)。
  • int get(index, snap_id) - 根据指定的 snap_id 选择快照,并返回该快照指定索引 index 的值。

示例:

输入:["SnapshotArray","set","snap","set","get"]
     [[3],[0,5],[],[0,6],[0,0]]
输出:[null,null,0,null,5]
解释:
SnapshotArray snapshotArr = new SnapshotArray(3); // 初始化一个长度为 3 的快照数组
snapshotArr.set(0,5);  // 令 array[0] = 5
snapshotArr.snap();  // 获取快照,返回 snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0);  // 获取 snap_id = 0 的快照中 array[0] 的值,返回 5

提示:

  • 1 <= length <= 50000
  • 题目最多进行50000 次setsnap,和 get的调用 。
  • 0 <= index < length
  • 0 <= snap_id < 我们调用 snap() 的总次数
  • 0 <= val <= 10^9

第一种思路:

暴力解,维护一个self.array,每次snap调用时,则遍历整个数组,把>0的元素和它的下标存在哈希表里。

会超时,因为每次snap都要扫一遍self.array。

第二种思路:

做一点优化,每次snap不再扫描整个self.array,而是直接copy上一次snap下来的记录,

然后只在set的时候修改对应的值,可以加快速度。

class SnapshotArray(object):
    from collections import defaultdict
    def __init__(self, length):
        """
        :type length: int
        """
        self.array = [0 for i in range(length)]
        self.history = dict()
        self.snap_id = -1
        self.history[self.snap_id] = dict()
    def set(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        self.history[self.snap_id][index] = val

    def snap(self):
        """
        :rtype: int
        """
        import copy
        
        self.snap_id += 1
        self.history[self.snap_id] = copy.deepcopy( self.history[self.snap_id - 1])
        return self.snap_id

    def get(self, index, snap_id):
        """
        :type index: int
        :type snap_id: int
        :rtype: int
        """
        snap_id -= 1
        if index in self.history[snap_id]:
            return self.history[snap_id][index]
        else:
            return 0


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

第三种思路:

随着测试数据量的不断增加,第二种方法也会超时,因此我们需要继续优化。

我们不妨不再复制数据,而是对于每一个index构建一个二维数组,里面存放所有历史记录,

[[snap_id, val]....]

比如: [[-1, 0], [2, 2]] 就代表这个记录的初始值为0,当snap_id 为 2 时,值为2

class SnapshotArray:
    def __init__(self, length: int):
        self.nums = []  #(snap_id, val)
        for _ in range(length):
            self.nums.append([[-1, 0]])
        self.snap_id = 0

    def set(self, index: int, val: int) -> None:
        if self.nums[index][-1][0] == self.snap_id:
            # update
            self.nums[index][-1][1] = val
        else:
            # insert
            self.nums[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:
        # use binary search to find the last pair where pair[0] <= snap_id
        candidates = self.nums[index]
        left, right = 0, len(candidates) - 1
        while left <= right:
            mid = (left + right) // 2
            if candidates[mid][0] == snap_id:
                return candidates[mid][1]
            elif candidates[mid][0] < snap_id:
                left = mid + 1
            else:
                right = mid - 1
        return candidates[right][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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值