【Leetcode】1146. Snapshot Array

题目地址:

https://leetcode.com/problems/snapshot-array/

要求实现一个数据结构,可以做如下操作:
1、SnapshotArray(int length)以一个长度 l l l初始化其为一个类似数组的数据结构,每个元素初始值为 0 0 0
2、void set(index, val)将某个位置设为给定值 v v v
3、int snap()将当前数组保存为快照,并返回当前的版本号,版本号等于;
4、int get(index, snap_id)返回第snap_id个版本的index位置的值。

法1:开个vector,然后每个位置把每个版本的历史值都存起来,get的时候按照版本号二分即可。在set的时候可以检查一下是否是最新的快照,如果是的话可以直接修改而不用多存一个pair。代码如下:

class SnapshotArray {
 public:
#define x first
#define y second
  vector<vector<pair<int, int>>> vs;
  int snap_id;

  SnapshotArray(int length) {
    snap_id = 0;
    vs.resize(length, {{-1, 0}});
  }

  void set(int index, int val) {
    auto &v = vs[index];
    if (v.back().x == snap_id) v.back().y = val;
    else v.push_back({snap_id, val});
  }

  int snap() {
    return snap_id++;
  }

  int get(int index, int snap_id) {
    // 一定要取引用,减少拷贝
    auto &v = vs[index];
    int l = 0, r = v.size() - 1;
    while (l < r) {
      int mid = l + (r - l + 1 >> 1);
      if (v[mid].x <= snap_id) l = mid;
      else r = mid - 1;
    }

    return v[l].y;
  }
};

初始化时间复杂度 O ( l ) O(l) O(l),set和snap复杂度 O ( 1 ) O(1) O(1),get复杂度 O ( log ⁡ v ) O(\log v) O(logv) v v v是get的位置有多少个版本,空间 O ( l ) O(l) O(l)

法2:可以参考可持久化Trie的做法,参考https://blog.csdn.net/qq_46105170/article/details/119029015。代码如下:

class SnapshotArray {
 public:
  struct Node {
    Node* ne[10];
    int val;
    Node(int x) : val(x) { fill(ne, ne + 10, nullptr); }
    Node() : Node(0) {}
  };
  vector<Node*> v;
  SnapshotArray(int length) { v.push_back(new Node()); }

  void set(int index, int val) {
    string s = to_string(index);
    auto *p = v.back(), *q = p;
    for (char ch : s) {
      int idx = ch - '0';
      if (!p->ne[idx]) {
        p->ne[idx] = new Node();
        p = p->ne[idx];
      } else {
        q = p->ne[idx];
        p->ne[idx] = new Node(q->val);
        p = p->ne[idx];
        copy(q->ne, q->ne + 10, p->ne);
      }
    }

    p->val = val;
  }

  int snap() {
    auto *p = new Node(), *q = v.back();
    copy(q->ne, q->ne + 10, p->ne);
    v.push_back(p);
    return v.size() - 2;
  }

  int get(int index, int snap_id) {
    string s = to_string(index);
    auto* p = v[snap_id];
    for (char ch : s) {
      int idx = ch - '0';
      if (!p->ne[idx]) return 0;
      p = p->ne[idx];
    }

    return p->val;
  }
};

每个操作时间复杂度 O ( 1 ) O(1) O(1),空间与操作次数成正比。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值