All O`one Data Structure

mail@pastecode.io avatar
unknown
plain_text
3 years ago
4.6 kB
2
Indexable
Never


/*
 * Implement the following interface. 
 *
 * All methods must run in O(1) time.
 */
 
interface AllForOne {
  
  
  
  /**
   * Increment the provided key's frequency value by 1.  Or add the key with the frequency 1 if it's not present.
   *
   * Note that the actual frequency value of the key is not necessary to expose to the caller; its value is only kept internally for bookkeeping purposes.
   */
  void incrementKey(String key);
  
  /**
   * Decrement the provided key's frequency value by 1.  Or remove the key if its frequency is 1.  Do nothing if the key is not present.
   *
   * Note that the actual frequency value of the key is not necessary to expose to the caller; its value is only kept internally for bookkeeping purposes.
   */
  void decrementKey(String key);
  
  /**
   * Get one of the keys with the max frequency, or empty string if there are no keys.
   */
  String getMaxKey();
   
  /**
   * Get one of the keys with the min frequency, or empty string if there are no keys.
   */
  String getMinKey();
}

/**
incrementKey("foo"); // void
incrementKey("foo"); // void
incrementKey("foo"); // void
incrementKey("foo"); // void
incrementKey("bar"); // void
incrementKey("bar"); // void
incrementKey("bar"); // void
incrementKey("bar"); // void
getMaxKey(); // "foo" or "bar" can be returned because foo -> 4, and bar -> 4
getMinKey(); // "foo" or "bar" can be returned because foo -> 4, and bar -> 4
decrementKey("foo"); // void
getMaxKey(); // "bar" because foo -> 3, and bar -> 4
getMinKey(); // "foo" because foo -> 3, and bar -> 4
decrementKey("foo"); // void
decrementKey("foo"); // void
decrementKey("foo"); // void
getMaxKey(); // "bar" because foo is not in the structure, and bar -> 4
getMinKey(); // "bar" because foo is not in the structure, and bar -> 4
*/

//[ ] ->0, [tom] -> 1, [felix, foo] -> 3 ,  [bar] -> 4

public class HelloWorld implements AllForOne {
  
  public class Node {
    
    Set<String> keys; // keys for the specific frequency
    int frequency;
    Node prev;
    Node next;
    
    public Node(int frequency) {
      this.key = new HashSet<>(); 
      this.frequency = frequency;
    }
  }
  
  Map<Integer, Node> frequencyToNode;
  Map<String, int> keyToFrequency;
  Node head;
  Node tail;
  
  public HelloWorld() {
    this.frequencyToNode = new HashMap<>();
    this.keyToFrequency = new HashMap<>();
    this.head = new Node(Integer.MIN_VALUE);
    this.tail = new Node(Integer.MAX_VALUE);
    this.head.next = tail;
    this.tail.prev = head;
  }
  
  /**
   * Increment the provided key's frequency value by 1.  Or add the key with the frequency 1 if it's not present.
   *
   * Note that the actual frequency value of the key is not necessary to expose to the caller; its value is only kept internally for bookkeeping purposes.
   */
  public void incrementKey(String key) {
    int frequency = this.keyToFrequency.GetOrDefault(key, 0);
    frequency += 1;
    this.keyToFrequency.put(key, frequency);
    
    Node prevNode = this.frequencyToNode.getOrDefault(frequency-1, null);
    if (prevNode != null) {
      prevNode.keys.remove(key);
      if (prevNode.keys.isEmpty()) {
        
        // Remove Empty Nodes
        secondPrevNode = prevNode.prev;
        nextNode = prevNode.next;
        
        secondPrevNode.next = nextNode;
        nextNode.prev = secondPrevNode;
          
          
        this.frequencyToNode.remove(frequency-1);
      }
    }
    
    if (this.frequencyToNode.contains(frequency)) {
      Node currNode = this.frequencyToNode.get(frequency);
      currNode.keys.add(key);
    } else {
      Node currNode = new Node(frequency);
      currNode.prev = prevNode;
      currNode.next = prevNode.next;
      preNode.next.pre = currNode;
      prevNode.next = currNode;
    }
  }
  
  /**
   * Decrement the provided key's frequency value by 1.  Or remove the key if its frequency is 1.  Do nothing if the key is not present.
   *
   * Note that the actual frequency value of the key is not necessary to expose to the caller; its value is only kept internally for bookkeeping purposes.
   */
  public void decrementKey(String key) {
  };
  
  /**
   * Get one of the keys with the max frequency, or empty string if there are no keys.
   * head -> 1 -> tail
   */
  public String getMaxKey() {
    if (tail.prev == head) {
      return "";
    }
    
    return tail.prev.keys.first();
  }
   
  /**
   * Get one of the keys with the min frequency, or empty string if there are no keys.
   */
  public String getMinKey();
    if (head.next == tail) {
      return "";
    }
    
    return head.next.keys.first();
}