• 【每日一题】1146. 快照数组-2024.4.26


    题目:

    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 的值。

    示例:

    输入:["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 次set,snap,和 get的调用 。
    • 0 <= index < length
    • 0 <= snap_id < 我们调用 snap() 的总次数
    • 0 <= val <= 10^9

    解答:

     

    代码:

    1. class SnapshotArray {
    2. //当前快照编号,初始值为0
    3. private int curSnapId;
    4. //每个index的历史修改记录
    5. private final Map<Integer,List<int[]>> history=new HashMap<>();
    6. public SnapshotArray(int length) {
    7. }
    8. public void set(int index, int val) {
    9. history.computeIfAbsent(index,k->new ArrayList<>()).add(new int[]{curSnapId,val});
    10. }
    11. public int snap() {
    12. return curSnapId++;
    13. }
    14. public int get(int index, int snap_id) {
    15. if(!history.containsKey(index)){
    16. return 0;
    17. }
    18. List<int[]> h=history.get(index);
    19. int j=search(h,snap_id);
    20. return j<0?0:h.get(j)[1];
    21. }
    22. //返回最大的下标i,满足h[i][0]<=x
    23. //如果不存在则返回-1
    24. private int search(List<int[]> h,int x){
    25. //开区间(left,right)
    26. int left=-1;
    27. int right=h.size();
    28. while(left+1<right){//区间不为空
    29. //循环不变量
    30. // h[left][0] <= x
    31. // h[right][1] > x
    32. int mid=left+(right-left)/2;
    33. if(h.get(mid)[0]<=x){
    34. left=mid;//区间缩小为(mid,right)
    35. }else{
    36. right=mid;//区间缩小为(left,mid)
    37. }
    38. }
    39. //根据循环不变量,此时h[left][0]<=x且h[left+1][0]=h[right][0]>x
    40. //所以left是最大的满足h[left][0]<=x的下标
    41. //如果不存在,则left为其初始值-1
    42. return left;
    43. }
    44. }
    45. /**
    46. * Your SnapshotArray object will be instantiated and called as such:
    47. * SnapshotArray obj = new SnapshotArray(length);
    48. * obj.set(index,val);
    49. * int param_2 = obj.snap();
    50. * int param_3 = obj.get(index,snap_id);
    51. */

    结果:

  • 相关阅读:
    Anomaly-Transformer (ICLR 2022 Spotlight)复现过程及问题
    459. 重复的子字符串(力扣LeetCode)
    【Unity面试】 最全NGUI和UGUI优化 | 面试真题 | UI框架 | 全面总结 |建议收藏
    C语言中malloc(),free(),calloc(),realloc()
    如何高效管理多个 Outlook 邮箱?
    力扣leetcode 827. 最大人工岛
    【Java中23种面试常考的设计模式之模板模式(Template)---行为型模式】
    Qt学习总结之QFrame和的QAbstractScrollArea
    《信息学奥赛一本通·初赛真题解析》
    2023 恒创海外服务器双11优惠汇总【附开通流程】
  • 原文地址:https://blog.csdn.net/weixin_45142381/article/details/138209917