• Leetcode: All O`one Data Structure


    Implement a data structure supporting the following operations:
    
    Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string.
    Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
    GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "".
    GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "".
    Challenge: Perform all these in O(1) time complexity.

    Solution: O(1) time complexity

    解题思路主要参考了网友ivancjw的帖子,数据结构参考了https://discuss.leetcode.com/topic/65634/java-ac-all-strict-o-1-not-average-o-1-easy-to-read用bucket,思路是,我们建立一个次数分层的结构,次数多的在顶层,每一层放相同次数的key值,例如下面这个例子:

    "A": 4, "B": 4, "C": 2, "D": 1

    那么用我们设计的结构保存出来就是:

    row0: val = 4, keys = {"A", "B"}
    row1: val = 2, keys = {"C"}
    row2: val = 1, keys = {"D"}

      1 public class AllOne {
      2     public class Bucket {
      3         int count;
      4         Bucket prev;
      5         Bucket next;
      6         HashSet<String> keySet;
      7         public Bucket(int num) {
      8             this.count = num;
      9             this.keySet = new HashSet<String>();
     10         }
     11     }
     12     
     13     Bucket head;
     14     Bucket tail;
     15     HashMap<String, Integer> keyCountMap;
     16     HashMap<Integer, Bucket> countBucketMap;
     17     
     18 
     19     /** Initialize your data structure here. */
     20     public AllOne() {
     21         this.head = new Bucket(Integer.MIN_VALUE);
     22         this.tail = new Bucket(Integer.MAX_VALUE);
     23         head.next = tail;
     24         tail.prev = head;
     25         this.keyCountMap = new HashMap<String, Integer>();
     26         this.countBucketMap = new HashMap<Integer, Bucket>();
     27     }
     28     
     29     /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
     30     public void inc(String key) {
     31         if (keyCountMap.containsKey(key)) {
     32             change(key, 1);
     33         }
     34         else {
     35             keyCountMap.put(key, 1);
     36             if (head.next.count != 1) {  //dont have the 1 bucket
     37                 addBucketAfter(new Bucket(1), head);
     38                 countBucketMap.put(1, head.next);
     39             }
     40             head.next.keySet.add(key);
     41         }
     42     }
     43     
     44     /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
     45     public void dec(String key) {
     46         if (keyCountMap.containsKey(key)) {
     47             int count = keyCountMap.get(key);
     48             if (count == 1) {
     49                 keyCountMap.remove(key);
     50                 removeKeyFromBucket(countBucketMap.get(count), key);
     51             }
     52             else change(key, -1);
     53         }
     54     }
     55     
     56     /** Returns one of the keys with maximal value. */
     57     public String getMaxKey() {
     58         return tail.prev==head? "" : (String)tail.prev.keySet.iterator().next();
     59     }
     60     
     61     /** Returns one of the keys with Minimal value. */
     62     public String getMinKey() {
     63         return head.next==tail? "" : (String)head.next.keySet.iterator().next();
     64     }
     65     
     66     public void change(String key, int offset) {
     67         //get count, update keyCountMap
     68         int count = keyCountMap.get(key);
     69         keyCountMap.put(key, count+offset);
     70         
     71         //get current bucket
     72         Bucket curBucket = countBucketMap.get(count);
     73   
     74         //new bucket
     75         Bucket newBucket;
     76         if (countBucketMap.containsKey(count+offset)) {
     77             newBucket = countBucketMap.get(count+offset);
     78         }
     79         else {
     80             newBucket = new Bucket(count+offset);
     81             countBucketMap.put(count+offset, newBucket);
     82             addBucketAfter(newBucket, (offset==1? curBucket : curBucket.prev));
     83         }
     84         newBucket.keySet.add(key);
     85         removeKeyFromBucket(curBucket, key);
     86     }
     87     
     88     public void removeKeyFromBucket(Bucket cur, String key) {
     89         cur.keySet.remove(key);
     90         if (cur.keySet.size() == 0) {
     91             removeBucketFromList(cur);
     92             countBucketMap.remove(cur.count);
     93         }
     94     }
     95     
     96     public void removeBucketFromList(Bucket cur) {
     97         cur.prev.next = cur.next;
     98         cur.next.prev = cur.prev;
     99         cur.next = null;
    100         cur.prev = null;
    101     }
    102     
    103     public void addBucketAfter(Bucket bucket, Bucket preBucket) {
    104         bucket.prev = preBucket;
    105         bucket.next = preBucket.next;
    106         preBucket.next.prev = bucket;
    107         preBucket.next = bucket;
    108     }
    109 }
    110 
    111 /**
    112  * Your AllOne object will be instantiated and called as such:
    113  * AllOne obj = new AllOne();
    114  * obj.inc(key);
    115  * obj.dec(key);
    116  * String param_3 = obj.getMaxKey();
    117  * String param_4 = obj.getMinKey();
    118  */

    Solution 2: 如果不要求O(1)time, 这个用两个heap方法很常规

     1 public class AllOne {
     2 
     3     class Node{
     4         String key;
     5         int val;
     6         public Node(String key, int val) {
     7             this.key = key;
     8             this.val = val;
     9         }
    10     }
    11     /** Initialize your data structure here. */
    12     HashMap<String, Node> map;
    13     PriorityQueue<Node> minQ;
    14     PriorityQueue<Node> maxQ;
    15     public AllOne() {
    16         map = new HashMap<String, Node>();
    17         minQ = new PriorityQueue<Node>(new Comparator<Node>(){
    18             public int compare(Node a, Node b) {
    19                 return a.val - b.val;
    20             }
    21         });        
    22         maxQ = new PriorityQueue<Node>(new Comparator<Node>(){
    23             public int compare(Node a, Node b) {
    24                 return b.val - a.val;
    25             }
    26         });
    27     }
    28     
    29     /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
    30     public void inc(String key) {
    31         if (!map.containsKey(key)) {
    32             map.put(key, new Node(key, 1));
    33             Node node = map.get(key);
    34             minQ.add(node);
    35             maxQ.add(node);
    36         } else {
    37             Node node = map.get(key);
    38             minQ.remove(node);
    39             maxQ.remove(node);
    40             node.val++;
    41             map.put(key, node);
    42             minQ.add(node);
    43             maxQ.add(node);
    44         }
    45     }
    46     
    47     /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    48     public void dec(String key) {
    49         if (map.containsKey(key)) {
    50             Node node = map.get(key);
    51             if (node.val == 1) {
    52                 map.remove(key);
    53                 minQ.remove(node);
    54                 maxQ.remove(node);
    55             } else {
    56                 minQ.remove(node);
    57                 maxQ.remove(node);
    58                 node.val--;
    59                 map.put(key, node);
    60                 minQ.add(node);
    61                 maxQ.add(node);
    62             }
    63         }
    64     }
    65     
    66     /** Returns one of the keys with maximal value. */
    67     public String getMaxKey() {
    68         return maxQ.isEmpty() ? "" : maxQ.peek().key;
    69     }
    70     
    71     /** Returns one of the keys with Minimal value. */
    72     public String getMinKey() {
    73         return minQ.isEmpty() ? "" : minQ.peek().key;
    74     }
    75 }
  • 相关阅读:
    SAP模块
    生產製造管理模块
    .NET Framework 3.5 SP1安装时下载文件问题及精简方法2(转)
    .NET Framework 3.5 SP1安装时下载文件问题及精简方法(转)
    .net remoting构架(part 2)转
    vbs下一些取特殊路径的方法总结(转)
    SQL安装命令行详解(转)
    InstallShield Basic MSI工程常见问题解答(转)
    在64位平台使用SQL Server Compact(转)
    vbs 创建多级目录方法
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/6139859.html
Copyright © 2020-2023  润新知