Leetcode1146. 快照数组

本文介绍了一种在LeetCode问题1146中使用哈希和二分查找技术来优化内存的快照数组实现方法。通过记录每个索引的历史修改记录并利用有序性进行查询,实现在O(1)和O(logq)的时间复杂度下操作,空间复杂度为O(q)。
摘要由CSDN通过智能技术生成

Every day a Leetcode

题目来源:1146. 快照数组

解法1:哈希 + 二分查找

每次调用 snap(),就复制一份数组的话,内存会爆。

为了节省内存,我们只存储修改的记录。调用 set(index,val) 时,不去修改数组,而是往 index 的历史修改记录末尾添加一条数据:此时的快照编号 cur_snap_id 和 val。

显然,历史修改记录中的快照编号是有序的。那我们在 get(int index, int snap_id) 时,就可以按 snap_id 做二分查找,找到编号小于等于 snap_id 的最新的修改记录,其中的 val 就是答案。

代码:

/*
 * @lc app=leetcode.cn id=1146 lang=cpp
 *
 * [1146] 快照数组
 */

// @lc code=start
class SnapshotArray
{
private:
    // 当前 snap_id
    int cur_snap_id = 0;
    // 每个 index 的历史修改记录
    unordered_map<int, vector<pair<int, int>>> history;

public:
    SnapshotArray(int length)
    {
    }

    void set(int index, int val)
    {
        auto p = pair<int, int>(cur_snap_id, val);
        history[index].push_back(p);
    }

    int snap()
    {
        return cur_snap_id++;
    }

    int get(int index, int snap_id)
    {
        auto &h = history[index];
        // 找快照编号 <= snap_id 的最后一次修改记录
        // 等价于找快照编号 >= snap_id+1 的第一个修改记录,它的上一个就是答案
        pair<int, int> p = {snap_id + 1, -1};
        int j = lower_bound(h.begin(), h.end(), p) - h.begin() - 1;
        return j >= 0 ? h[j].second : 0;
    }
};

/**
 * Your SnapshotArray object will be instantiated and called as such:
 * SnapshotArray* obj = new SnapshotArray(length);
 * obj->set(index,val);
 * int param_2 = obj->snap();
 * int param_3 = obj->get(index,snap_id);
 */
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:初始化、set、snap 均为 O(1),get 为 O(log⁡q),其中 q 为 set 的调用次数。

空间复杂度:O(q),其中 q 为 set 的调用次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值