public int bestFit(final long[] w) {

        final BST bst = new BST();
        // initialize a root
        bst.root = new TreeNode(w[0], null, null);
        final int numOfWeights = w.length;
        int binCount = 0;

        for (int i = 0; i < numOfWeights; i++) {
            // check bins for each weight
            final long weight = w[i];
            long minDiff = 1;
            // get the new root each iteration
            TreeNode node = bst.root;
            TreeNode minNode = null;

            while (node != null) {
                // compare bin left space and current weight
                if (node.value > weight) {
                    final long diff = node.value - weight;
                    if (diff < minDiff) {
                        minDiff = diff;
                        minNode = node;
                        node = node.left;
                    } else {
                        throw new RuntimeException("something is wrong. this shouldn't happen and there shouldn't be duplicates in binary search tree.");
                    }
                } else {
                    node = node.right;
                }
            }

            if (minNode == null) {
                binCount++;
                final TreeNode newNode = new TreeNode(1 - weight, null, null);
                bst.insert(newNode.value);
            } else {
                minNode.value -= weight;
                bst.remove(minNode.value);
                bst.insert(minNode.value);
            }

        }

        return binCount;

    }