public void add(Integer elem) {

    ensureCapacity();

    Object[] leaf = getLeaf();

    leaf[jPointer++] = elem;

    size++;

  }
This is the implementation of Hashed Array Tree (HAT) data structure that is the same as Dynamic
Array (ArrayList in Java) in terms of time complexity, however, it wastes O(SQRT(N)) extra space
when increasing capacity.

Although name implies hashing, HAT does not use any hash.

Initially, we start with base array  that stores only references to leaf arrays whose size is
the same as base array. Every time current leaf array is full we create new leaf array and start
to insert data into newly created leaf array.

When increasing capacity, we double size of base array and leaf create leaf arrays with doubles
size and copy entries from previous HAT. In this way, only quarter of newly created HAT is full
and other leaf arrays will be null.
src/ds/HashedArrayTree.java