LeetCode每日一题(1146. Snapshot Array)

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 <= 50000
  • At most 50000 calls will be made to set, snap, and get.
  • 0 <= index < length
  • 0 <= snap_id < (the total number of times we call snap())
  • 0 <= val <= 10^9

思路很简单, 看到条件中的 length <= 50000, 我们首先应该排除真的给整个数组做快照, 否则超时是妥妥的了, 我们在数组里保存每个值的历史状态,但是这里要考虑一个前提条件,就是如果在设置之前拍过快照,那我们就需要新建一个历史状态, 否则的话我们只需要修改最后一个历史状态即可。然后获取的时候我们只需要二分查找每个值的历史记录即可。这里要注意一点,我们在 SnapshotArray 中维护一个下一个快照的 id, 每次 snap 之后,该 id+1, 在获取的时候, 只有历史状态里的 snap_idx 小于该值才是拍过快照的历史, 因为最后一个历史状态有可能是没有拍过快照的。

捎带说一句, 这题如果用 HashMap 来保存历史使用的内存可能会更小, 但是如果不做初始化, 判断情况会复杂很多, 在无数次试错后我放弃了, 感兴趣的同学可以试试


struct SnapshotArray {
    s: i32,
    l: Vec<Vec<(i32, i32)>>,
}

impl SnapshotArray {
    fn new(length: i32) -> Self {
        Self {
            s: 0,
            l: vec![vec![(0, 0)]; length as usize],
        }
    }

    fn set(&mut self, index: i32, val: i32) {
        if self.s > self.l[index as usize].last().unwrap().0 {
            self.l[index as usize].push((self.s, val));
            return;
        }
        self.l[index as usize].last_mut().unwrap().1 = val;
    }

    fn snap(&mut self) -> i32 {
        self.s += 1;
        self.s - 1
    }

    fn get(&self, index: i32, snap_id: i32) -> i32 {
        let history = &self.l[index as usize];
        let mut l = 0;
        let mut h = history.len() - 1;
        while l < h {
            let m = (l + h) / 2;
            if history[m].0 == snap_id {
                return history[m].1;
            } else if history[m].0 < snap_id {
                l = m + 1;
            } else {
                h = m;
            }
        }
        if history[l].0 == self.s || history[l].0 > snap_id {
            return history[l - 1].1;
        }
        return history[l].1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值