private V put(ArrayNode parent, Node node, byte height, int key, V value) {
    if (node instanceof KeyValueNode) {
      KeyValueNode<V> kvNode = (KeyValueNode<V>) node;
      if (key == kvNode.key) {
        // Key already exists as key-value pair, replace value
        kvNode.value = value;
        return value;
      }
      // Key already exists but doesn't match current key
      KeyValueNode<V> oldParent = kvNode;
      int newParentPosition = getPosition(height - 1, key);
      int oldParentPosition = getPosition(height, oldParent.key);
      int childPosition = getPosition(height, key);
      ArrayNode newParent = new ArrayNode(parent, key, height);
      newParent.parent = parent;
      if (parent == null) {
        // Only the root doesn't have a parent, so new root
        root = newParent;
      } else {
        // Add the child to the parent in it's parent's position
        parent.addChild(newParentPosition, newParent);
      }
      if (oldParentPosition != childPosition) {
        // The easy case, the two children have different positions in parent
        newParent.addChild(oldParentPosition, oldParent);
        oldParent.parent = newParent;
        newParent.addChild(childPosition, new KeyValueNode<V>(newParent, key, value));
        return null;
      }
      while (oldParentPosition == childPosition) {
        // Handle the case when the new children map to same position.
        height++;
        if (height > MAX_DEPTH) {
          // We have found two keys which match exactly.
          System.err.println("Yikes! Found two keys which match exactly.");
          return null;
        }
        newParentPosition = getPosition(height - 1, key);
        ArrayNode newParent2 = new ArrayNode(newParent, key, height);
        newParent.addChild(newParentPosition, newParent2);

        oldParentPosition = getPosition(height, oldParent.key);
        childPosition = getPosition(height, key);
        if (oldParentPosition != childPosition) {
          newParent2.addChild(oldParentPosition, oldParent);
          oldParent.parent = newParent2;
          newParent2.addChild(childPosition, new KeyValueNode<V>(newParent2, key, value));
        } else {
          newParent = newParent2;
        }
      }
      return null;
    } else if (node instanceof ArrayNode) {
      ArrayNode arrayRoot = (ArrayNode) node;
      int position = getPosition(arrayRoot.height, key);
      Node child = arrayRoot.getChild(position);
      if (child == null) {
        // Found an empty slot in parent
        arrayRoot.addChild(position, new KeyValueNode<V>(arrayRoot, key, value));
        return null;
      }
      return put(arrayRoot, child, (byte) (height + 1), key, value);
    }
    return null;
  }