Buttercola: O(1) Map


Constant Clear Map
Buttercola: O(1) Map
Design a Map so that it supports the following operations:
1. add(int val), O(1) time
2. remove(int val), O(1) time
3. contains(int val), O(1) time
4. clear(), O(1) time
5. iterate(), O(num of elements)

- use version to track valid element in map. Analysis:
If we just use a randomized array, i.e, a hash map, add(), remove(), and contains() operations take O(1) time. The clear() takes O(size of array) time (NOT SURE), and iterate takes O(size of array) time. Note that iterate() takes O(size of array) time instead of O(num of elements) because of the implementation of a hash map is usually an array or array + list. So it needs to iterate all elements of the array no matter if it is taken or not. 

If we only use a sequential accessed array, i.e, an ArrayList in Java, the add() takes O(1), but remove() and contains() takes O(num of elements) time. clear() takes O(1) ?? not sure. 
iterate() takes O(num of elements) time as well. 

So the idea is to combine the two data structures together. 
class Solution implements Iterable<Integer> {
  private int[] list;
  private Map<Integer, Integer> map;
  private int size;
  private final int INIT_CAPACITY = 4;
   
  public Solution() {
    list = new int[INIT_CAPACITY];
    map = new HashMap<>();
    size = 0;
  }
   
  public void add(int val) {
    if (size == list.length) {
      resize(2 * list.length);
    }
     
    map.put(val, size);
    list[size] = val;
    size++;
  }
   
  public void remove(int val) {
    if (!map.containsKey(val)) {
      throw new NoSuchElementException();
    }
     
    // step 1: get the index of the val to be removed
    int idxToRemove = map.get(val);
     
    // step 2: move the last element to the index to be removed
    int lastE = list[size - 1];
    list[idxToRemove] = lastE;
    //list[size - 1] = null;
     
    size--;
    map.remove(val);
    map.put(lastE, idxToRemove);
     
    // shrink the array
    if (size > 0 && size == list.length / 4) {
      resize(list.length / 2);
    }
     
  }
   
  public boolean contains(int val) {
    return map.containsKey(val) &&
           map.get(val) < size &&
           val == list[map.get(val)];
  }
  public void clear() {
    size = 0;
  }
   
  @Override
  public Iterator<Integer> iterator() {
    return new MyListIterator();
  }
   
  private class MyListIterator implements Iterator<Integer> {
    private int i = 0;
     
    @Override
    public boolean hasNext() {
      return i < size;
    }
     
   @Override
    public Integer next() {
      Integer result = 0;
      if (hasNext()) {
        result = (Integer) list[i];
        i++;
      }
       
      return result;
    }
     
    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
   
  private void resize(int newSize) {
    int[] newList = new int[newSize];
    newList = Arrays.copyOf(list, size);
    list = newList;
  }
Use two arrays, map[n] and list[n], where for the map[i], the index stores the val of the data, and its value stores the index of the data in the list array. The real value is stored in the list array as well for the convenience of iterator() in O(num of elements) time. 

The basic idea of this solution is very close the method 1, just to use the map[] array to simulate a hash map. Therefore here we assume that the size of the map[] array is unlimited and the value of the data to be stored is never out of boundary. 
  private Integer[] map;
  private Integer[] list;
  private int size;
  private final int INIT_CAPACITY = 4;
  private final int MAP_CAPACITY = 1000;
   
  public Solution() {
    list = new Integer[INIT_CAPACITY];
    map = new Integer[MAP_CAPACITY];
    this.size = 0;
  }
   
  public void add(int val) {   
    if (size == list.length) {
      resize(2 * list.length);
    }
     
    map[val] = size;
    list[size] = val;
    size++;
  }
   
  public void remove(int val) {
    if (!contains(val)) {
      throw new NoSuchElementException();
    }
     
    // step 1: get the index of the val to be removed
    int idxToRemove = map[val];
     
    // step 2: move the last element to the index to be removed
    int lastE = list[size - 1];
    list[idxToRemove] = lastE;
    list[size - 1] = null;
     
    size--;
     
    map[lastE] = idxToRemove;
    map[val] = null;
     
     
     
    // shrink the array
    if (size > 0 && size == list.length / 4) {
      resize(list.length / 2);
    }
  }
   
  public boolean contains(int val) {
    return map[val] != null &&
           map[val] < size &&
           val == list[map[val]];
  }
  public void clear() {
    size = 0;
  }
   
  @Override
  public Iterator<Integer> iterator() {
    return new MyListIterator();
  }
   
  private class MyListIterator implements Iterator<Integer> {
    private int i = 0;
     
    @Override
    public boolean hasNext() {
      return i < size;
    }
     
   @Override
    public Integer next() {
      Integer result = 0;
      if (hasNext()) {
        result = list[i];
        i++;
      }
       
      return result;
    }
     
    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
   
  private void resize(int newSize) {
    Integer[] newList = new Integer[newSize];
    for (int i = 0; i < size; i++) {
      newList[i] = list[i];
    }
    list = newList;
  }
   
  public static void main(String[] args) {
    Solution sol = new Solution();
    sol.add(1);
    sol.add(3);
    //sol.add(5);
     
    //System.out.println(sol.contains(3));
     
    sol.clear();
     
    sol.add(4);
    sol.add(5);
     
    System.out.println(sol.contains(3));
     
    //sol.remove(3);
     
     
    Iterator<Integer> it = sol.iterator();
    while (it.hasNext()) {
      int val = it.next();
      System.out.println(val);
    }
     
  }
Read full article from Buttercola: O(1) Map

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts