• JAVA 模拟数据结构


    模拟一些数据结构/容器

    剑指 Offer 59 - II. 队列的最大值

    难度中等

    请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_valuepush_back 和 pop_front 的均摊时间复杂度都是O(1)。

    若队列为空,pop_front 和 max_value 需要返回 -1

    方法1 ;数组模拟

    class MaxQueue {
       int que[]  =new int[20005];
       int sta=0,end=0;
        public MaxQueue() {
        }
        public int max_value() {
            
               int ans  =-1;
               for(int i=sta;i<end;i++)  ans=Math.max(ans,que[i]);
               return ans;
        }
        public void push_back(int value) {
                  que[end++]  =value;
        }
        public int pop_front() {
            if(sta==end)  return -1;
                 return que[sta++];
        }
    }
    
    /**
     * Your MaxQueue object will be instantiated and called as such:
     * MaxQueue obj = new MaxQueue();
     * int param_1 = obj.max_value();
     * obj.push_back(value);
     * int param_3 = obj.pop_front();
     */
     max_value() 的时间复杂度 O(n)

    方法2 :链表模拟

    class MaxQueue {
       class Node{
           int val;
           Node next;
           public Node (int val){
               this.val  =val;
           }
       }
        Node first,last,max;
        public MaxQueue() {
          
        }
        
        public int max_value() {
                if(first==null)  return -1;
                return max.val;
        }
        
        public void push_back(int value) {
               Node tmp   =new Node(value);
              if(first==null) {
                  first  =tmp;
                  max  = tmp;
                  last  = tmp;
                  return ;
              }
               last.next  =tmp;
               last  =tmp;
                if(tmp.val>max.val)  max  =tmp;
        }
        
        public int pop_front() {
                if(first==null) return -1;
                Node te  =first;       
                if(first.next==null){//最后一个
                    last  =null;
                    max=null;     
                }  
                if(first.next!=null&&first.val==max.val){//当前值为最大值,需要更新max
                    Node  q  =first.next;
                    max  = first.next;
                    while(q!=null){
                                    if(q.val>max.val){
                                            max  =q;
                                    }
                                    q  = q.next;
                                }
                }
                first  =first.next;
                return te.val;
        }
    }
    
    /**
     * Your MaxQueue object will be instantiated and called as such:
     * MaxQueue obj = new MaxQueue();
     * int param_1 = obj.max_value();
     * obj.push_back(value);
     * int param_3 = obj.pop_front();
     */
    方法3:队列+双端队列

    class MaxQueue {
      Queue<Integer>que;
      Deque<Integer>deque;
        public MaxQueue() {
               que  =new LinkedList();
               deque  =new LinkedList();
        }
        
        public int max_value() {
            if(deque.isEmpty())  return -1;
            return deque.peekFirst();
        }
        // 1 5 2 3
        // deque 5 3  5:que中5后面没有比5大的数,只要还没pop_front 5,5就是当前que中的最大值。3同理
        // que   5 2 3
        public void push_back(int value) {
               while(!deque.isEmpty()&&value>deque.peekLast()) deque.pollLast();
               deque.offerLast(value);
               que.offer(value);
        }
        
        public int pop_front() {
                  if(que.isEmpty())  return -1;
                  int ans  =que.peek();
                  que.poll();
                  if(ans==deque.peekFirst()) deque.pollFirst();
                  return ans;
        }
    }
    
    /**
     * Your MaxQueue object will be instantiated and called as such:
     * MaxQueue obj = new MaxQueue();
     * int param_1 = obj.max_value();
     * obj.push_back(value);
     * int param_3 = obj.pop_front();
     */

    146. LRU 缓存

    难度中等
    请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。
    实现 LRUCache 类:
    • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
    • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
    • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

    函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

    //1 数组+双向链表
    class LRUCache {
        class Node{
            int key,value;
            Node pre,next;
            public Node(){}
            public Node(int key,int value){
                this.key  =key;
                this.value  =value;
            }
        }
        Node map[];
        Node head,tail;
        int capacity,size;
        public LRUCache(int capacity) {
                map  = new Node[10005];
                head  =new Node();
                tail =new Node();
                head.next =  tail;
                tail.pre  =head;
                this.capacity  =capacity;
        }
        //只要访问该key(不包含逐出)就放到最前面,因此tail.pre就始终为最久未使用
        public int get(int key) {
               if(map[key]==null)  return -1;
               return add(remove(map[key])).value;//放到最前面,必须先删后添加
        } 
        public void put(int key, int value) {
                if(map[key]==null){
                    map[key]  =add(new Node(key,value));
                    if(++size>capacity){
                        map[remove(tail.pre).key]=null;//不仅删除节点,还要在map中删除,因为get时通过Map判断key是否存在
                    }
                }
                add(remove(map[key])).value  =value;
        }
        public Node add(Node node){
            Node tmp  =head.next;
            head.next  = node;
            node.pre =head;
            tmp.pre  =node;
            node.next  =tmp;
            return node;
        }
        public Node remove(Node node){
          node.pre.next  = node.next;
          node.next.pre  =node.pre;
            return node;
        }
    }
    
    /**
     * Your LRUCache object will be instantiated and called as such:
     * LRUCache obj = new LRUCache(capacity);
     * int param_1 = obj.get(key);
     * obj.put(key,value);
     */

     2 数组模拟

    class LRUCache {
        int record[];
        int time[];
        int kv[];
        int l,r,size,capacity;
        public LRUCache(int capacity) {
                record  =new int[200010];
                time  =new int[10005];
                kv =new int[10006];
                Arrays.fill(kv,-1);
                l = 0;
                r  =0;
                size=0;
                this.capacity  =capacity;
        }   
        public int get(int key) {
            // 先判断这个key存不存在,不存在也不会记录
            if (kv[key] == -1) {
                return -1;
            }
                record[r]  =key;
                time[key]  =r++;
                return kv[key];
        } 
        public void put(int key, int value) {    
               record[r]  =key;
               time[key] =r++;
               if(kv[key]==-1){
                   if(size<capacity) size++;//由于size>capacity就会逐出一个数据,size不能一直++
                   else{
                               while(l<r&&time[record[l]]!=l)  
                                {
                                    //   System.out.println(l);
                                    //    System.out.println("rec: "+ record[l]+"time"+time[record[l]]);
                                    l++;//第一个后面没有再被用的数据就是最久未使用的数据
    
                                }
                              kv[record[l++]]  =-1;
                   }           
               }
               kv[key]  =value;
        }
    }
    
    /**
     * Your LRUCache object will be instantiated and called as such:
     * LRUCache obj = new LRUCache(capacity);
     * int param_1 = obj.get(key);
     * obj.put(key,value);
     */

    706. 设计哈希映射

    难度简单

    不使用任何内建的哈希表库设计一个哈希映射(HashMap)。

    实现 MyHashMap 类:

    • MyHashMap() 用空映射初始化对象
    • void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。
    • int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
    • void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。
    class MyHashMap {
        LinkedList table[];
        final int num  =769;
        class Node{
            int key,value;
            public Node(int key,int value){
                this.key  =key;
                this.value  =value;
            }
            public int getkey(){
                return key;
            }
             public void setvalue(int value){
                this.value  =value;
            }
              public int getvalue(){
                 return  value;
            }
        
        }
        public MyHashMap() {
             table  =new LinkedList[10007];
                for(int i =0;i<num;i++){
             table[i] = new LinkedList<Node>();
         }
        }
        
        public void put(int key, int value) {
             int hash = key%num;
             LinkedList  head = table[hash];
             Iterator<Node>ite  = head.iterator();
             while(ite.hasNext()){
                 Node tmp  =ite.next();
                 if(tmp.key==key){
                     tmp.setvalue(value);
                     return;
                 }
             }
             head.addLast(new Node(key,value));
    
    
        }
        
        public int get(int key) {
             int hash = key%num;
             LinkedList  head = table[hash];
             Iterator<Node>ite  = head.iterator();
            while(ite.hasNext()){
                 Node tmp  =ite.next();
                 if(tmp.key==key){
                    
                     return tmp.getvalue();
                 }
             }
             return -1;
        }
        
        public void remove(int key) {
             int hash = key%num;
             LinkedList  head = table[hash];
             Iterator<Node>ite  = head.iterator();
            while(ite.hasNext()){
                 Node tmp  =ite.next();
                 if(tmp.key==key){
                     head.remove(tmp);
                     return ;
                 }
             }
             
        // }
        // public void remove(int key) {
        //     int hash  =key%num;
        //     LinkedList  head = table[hash];
        //     Iterator<Node>ite  =head.iterator();
        //     while(ite.hasNext()){
        //         Node tmp  =  ite.next();
        //         if(tmp.getkey()==key){
        //              table[hash].remove(tmp);
        //              return ;
        //         }
        //     }
        // }
        }
    }
    
    /**
     * Your MyHashMap object will be instantiated and called as such:
     * MyHashMap obj = new MyHashMap();
     * obj.put(key,value);
     * int param_2 = obj.get(key);
     * obj.remove(key);
     */

    哈希冲突

    https://blog.csdn.net/qq_48241564/article/details/118613312

    1 、 开放定址法:我们在遇到哈希冲突时,去寻找一个新的空闲的哈希地址。

    1.1 线性探测法

    当我们的所需要存放值的位置被占了,我们就往后面一直加1并对m取模直到存在一个空余的地址供我们存放值,取模是为了保证找到的位置在0~m-1的有效空间之中。

    公式:h(x)=(Hash(x)+i)mod (Hashtable.length);(i会逐渐递增加1)
    ————————————————

    1.2  平方探测法(二次探测)

                     当我们的所需要存放值的位置被占了,会前后寻找而不是单独方向的寻找。

            公式:h(x)=(Hash(x) +i)mod (Hashtable.length);(i依次为+(i^2)和-(i^2))

    2  再哈希法:同时构造多个不同的哈希函数,等发生哈希冲突时就使用第二个、第三个……等其他的哈希函数计算地址,直到不发生冲突为止。虽然不易发生聚集,但是增加了计算时间。

    3、链地址法:将所有哈希地址相同的记录都链接在同一链表中。

    公式:h(x)=xmod(Hashtable.length);

    4   建立公共溢出区:将哈希表分为基本表和溢出表,将发生冲突的都存放在溢出表中。

  • 相关阅读:
    2020阿里最新出品的泰山版Java开发手册,告别垃圾代码
    freecplus框架-目录操作
    freecplus框架简介
    freecplus框架-加载参数文件
    freecplus框架-xml解析
    freecplus框架-tcp网络通信
    freecplus框架-PostgreSQL数据库操作
    freecplus框架-Oracle数据库操作
    freecplus框架-MySQL数据库操作
    freecplus框架-ftp客户端
  • 原文地址:https://www.cnblogs.com/tingtin/p/15842545.html
Copyright © 2020-2023  润新知