初学python记录:力扣1146. 快照数组

题目:

实现支持下列接口的「快照数组」- 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 的值。

思考:

暴力解法

用一个长度为length的数组记录当前的数组值,用一个字典记录每一次快照时的数组和快照编号,代码如下:

class SnapshotArray(object):

    def __init__(self, length):
        """
        :type length: int
        """
        self.array = [0 for _ in range(length)]
        self.snapshot = {}
        self.snap_time = -1


    def set(self, index, val):
        """
        :type index: int 
        :type val: int
        :rtype: None
        """
        self.array[index] = val


    def snap(self):
        """
        :rtype: int
        """
        self.snap_time += 1
        self.snapshot[self.snap_time] = list(self.array)    # 使用 list() 确保存储的是数组的副本
        return self.snap_time


    def get(self, index, snap_id):
        """
        :type index: int
        :type snap_id: int
        :rtype: int
        """
        return self.snapshot[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)

提交卡在第 69 / 75 个例子,超内存了:

优化(参考灵神的题解)

不需要每次快照的时候都把数组复制下来,由于get()函数是通过给定的 snap_id 和 index 得到对应值,那我们就用一个数据结构(命名为history)记录所有(改变过值的)数组元素每次改变时的快照次数snap_time和改变后的值val,即(snap_time, val)。

这样,调用get()函数即:找到index对应的数组元素的history,在history中找到满足snap_time < snap_id条件的最后一个(snap_time, val)对,val即为所求。

问题一、history用什么数据结构?

整体用字典存储,键是每个元素的index,值是每个元素的history(用列表存储(snap_time, val)对)。

问题二、怎么在history中找到满足snap_time ≤ snap_id条件的最后一个(snap_time, val)对

因为history中的(snap_time, val)对是按照snap_time从小到大排列的,所以可以用二分查找提高效率。

代码如下:

class SnapshotArray(object):

    def __init__(self, length):
        """
        :type length: int
        """
        self.history = defaultdict(list)
        self.cur_snap = -1


    def set(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        # 记录(snap_time, val)对
        self.history[index].append([self.cur_snap, val])


    def snap(self):
        """
        :rtype: int
        """
        self.cur_snap += 1
        return self.cur_snap


    def get(self, index, snap_id):
        """
        :type index: int
        :type snap_id: int
        :rtype: int
        """
        # 在index对应元素的history中找到满足snap_time < snap_id条件的最后一个(snap_time, val)对,val即为所求
        # 如果元素没有修改过,直接返回0
        L = self.history[index]
        if not L:
            return 0

        # 二分查找
        left = 0
        right = len(L) - 1
        ans = 0
        
        while left <= right:
            mid = (left + right) // 2
            if L[mid][0] < snap_id:
                ans = L[mid][1]
                left = mid + 1
            else:
                right = mid - 1
        return ans


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

提交通过:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值