Java Code Review: Merge sorted lists into a single sorted list

java, list, sorting

Solution

Your solution is probably the fastest one. SortedLists have an insert cost of log(n), so you'll end up with M log (M) (where M is the total size of the lists).

Adding them to one list and sorting, while easier to read, is still M log(M).

Your solution is just M.

You can clean up your code a bit by sizing the result list, and by using a reference to the lowest list instead of a boolean.

public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) {
    int totalSize = 0; // every element in the set
    for (List<T> l : lists) {
        totalSize += l.size();
    }

    List<T> result = new ArrayList<T>(totalSize);

    List<T> lowest;

    while (result.size() < totalSize) { // while we still have something to add
        lowest = null;

        for (List<T> l : lists) {
            if (! l.isEmpty()) {
                if (lowest == null) {
                    lowest = l;
                } else if (l.get(0).compareTo(lowest.get(0)) <= 0) {
                    lowest = l;
                }
            }
        }

        result.add(lowest.get(0));
        lowest.remove(0);
    }

    return result;
}

If you're really particular, use a List object as input, and lowest can be initialized to be lists.get(0) and you can skip the null check.

Problem

I want to merge sorted lists into a single list. How is this solution? I believe it runs in O(n) time. Any glaring flaws, inefficiencies, or stylistic issues? I don't really like the idiom of setting a flag for "this is the first iteration" and using it to make sure "lowest" has a default value. Is there a better way around that? ``` public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) { List<T> result = new ArrayList<T>(); int totalSize = 0; // every element in the set for (List<T> l : lists) { totalSize += l.size(); } boolean first; //awkward List<T> lowest = lists.iterator().next(); // the list with the lowest item to add while (result.size() < totalSize) { // while we still have something to add first = true; for (List<T> l : lists) { if (! l.isEmpty()) { if (first) { lowest = l; first = false; } else if (l.get(0).compareTo(lowest.get(0)) <= 0) { lowest = l; } } } result.add(lowest.get(0)); lowest.remove(0); } return result; } ``` Note: this isn't homework, but it isn't for production code, either.

Original source