How would you Merge Multiple Sorted Lists of Strings into one list? I got asked this very question in an interview myself. And to my surprise I was not very sharp on it. The question is about developing an algorithm to find how to merge an arbitrary number K of Sorted Lists of Strings into 1.

So let us start with our usual clarification portion and make some assumptions:

- Obviously all the lists are sorted. (As advised by the question itself)
- The lists contain Strings. (Again, denoted by the question)
- Let us denote the longest list as having N elements. (This will help us develop big-O notations later)

There is not any other clarifications that we need. Hence we can start to think about a way to solve this.

How would our own brain solve this? It would just compare each first item on the list, write it down and remove it from the list, until all element of all lists are out. Seems like we have our hands on a brute force solution!

## Merge Multiple Sorted Lists of Strings – Recursive Algorithm

- While lists are not empty:
- For each List:
- Compare the heads of the lists
- Remove and print out the smallest number

But let us do a little bit space-time complexity analysis on this. We are looping through each list (K) for each element across lists (N*K). The result would be that our Time Complexity is **O(nk ^{2})**. A note to make is that by having the lists as LinkedLists or by keeping an index in the lists instead of actually removing the item, we could make our last step (Remove and print out the head of the list), O(1).

The auxiliary space complexity on the other hand is O(1) since we are not keeping any data structured in our algorithm ;D. Given this info let us think about any trade-offs we can make by using some space and lowering our runtime.

For this we can try to take another look at the problem and see if we can split it into sub-problems. As it turns out this question is a little bit similar to MergeSort. Quoting from our MergeSort post:

## Merge Sort Algorithm

- Divide the unsorted list into 2 sublists.
- Sort them (using recursion of merge sort).
- Merge the two sorted list in a merge step to produce 1 sorted list.

For more information you can take a look at this excellent explanation from Khan Academy

Now in our current problem’s case to merge multiple sorted lists of strings, we already have the lists sorted. So all we need to do is focus on the algorithm to merge them. Our current algorithm will look like this:

## Merge Multiple Sorted Lists of Strings – Loop Algorithm

- While there are more than 1 lists left.
- Merge a pair of lists into 1 and append it to the list of lists. Remove the merged ones.

Note that the above can also translate the above solution into a recursive solution:

## Merge Multiple Sorted Lists of Strings – Recursive Algorithm

- Divide the lists into two groups.
- Merge each group on its own (in a recursive fashion).
- Merge the two groups together.

So let’s try to put both those algorithms (which are fairly similar) into a code implementation. Note that they should be fairly similar, as the merge step will look the same.

### Merge Multiple Sorted Lists of Strings – Java Loop Implementation

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
public class Solution { public ArrayList<String> mergeMultipleLists(ArrayList<ArrayList<String>> stringLists) { LinkedList<String> queue = new LinkedList<String>(); for (int i = 0; i < stringLists.size(); i++) { queue.add(stringLists.get(i)); } while (queue.size() > 1) { ArrayList<String> firstList = queue.poll(); ArrayList<String> secondList = queue.poll(); ArrayList<String> mergedList = Solution.merge(firstList, secondList); queue.add(mergedList); // put all lists in a queue } return queue.poll(); } // This merge steps take O(N1+N2) where N# is the number of elements of each list public static ArrayList<String> merge(ArrayList<String> firstList, ArrayList<String> secondList) { ArrayList<String> mergedList = new ArrayList<String>(); int firstListIndex = 0; int secondListIndex = 0; while (firstList.size() > firstListIndex && secondList.size() > secondListIndex) { String currentFirst = firstList.get(firstListIndex); String currentSecond = secondList.get(secondListIndex); firstList.get(0); if (currentFirst.compareTo(currentSecond) > 0) { mergedList.add(currentFirst); firstListIndex++; } else { mergedList.add(currentSecond); secondListIndex++; } } // Add any remaining values if (firstList.size() > firstListIndex) { String current = secondList.get(secondListIndex); mergedList.add(current); firstListIndex++; } if (secondList.size() > secondListIndex) { String current = secondList.get(secondListIndex); mergedList.add(current); secondListIndex++; } return mergedList; } } |

So for some quick analysis. We are merging lists in a tree fashion. At the beginning step we are merging N/2 lists, whereas at the end step we are merging 2. Therefore we are doing **O(K*log(K))** merges. For each merge we are going through the elements of both lists. Denoting their length with N, our time complexity for doing 1 merge will be **(O(N))**. Hence our final time complexity will be found by multiplying those two actions, which will mean **O(N*K*log(K))**. A lot better than our brute force approach isn’t it! On the other hand, since we are keeping all lists with all elements in an auxiliary data structure, our space complexity will be **O(N*K)**.

So far so good! But why don’t we take a stab at the recursive approach? If you are still beginning in Computer Science, brush up your knowledge by reading this small lecture on recursion

### Merge Multiple Sorted Lists of Strings – Java Recursive Implementation

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class Solution { public ArrayList<String> mergeMultipleLists(ArrayList<ArrayList<String>> stringLists) { return Solution.mergeMultipleListsHelper(stringLists, 0, stringLists.size()-1); } public static ArrayList<String> mergeMultipleListsHelper( ArrayList<ArrayList<String>> stringLists int startIndex int endIndex ) { int midIndex = (startIndex + endIndex) / 2; ArrayList<ArrayList<String>> mergedLeft = mergeMultipleListsHelper(startIndex, midIndex); ArrayList<ArrayList<String>> mergedRight = mergeMultipleListsHelper(midIndex+1, endIndex); return Solution.merge(mergedLeft, mergedRight); } public static ArrayList<String> merge(ArrayList<String> firstList, ArrayList<String> secondList) { ... // As perviously implemented ... } } |

**Homework #1:** What’s the time and space complexity of the above code? Can you explain why?

Seems like this was not too hard either. As you can see if you start on step by step blocks and try to reason out the problem first before jumping into coding, the whole process becomes much easier.

Now what if our interviewer does not like this or for some reason wants to point us to a different direction? Another solution, which in my opinion is a little less straight forward than the ones above, is to use a Heap data structure.

Quoting from wikipedia:

In computer science, a heap is a specialized tree-based data structure that satisfies the heap property: If A is a parent node of B then the key of node A is ordered with respect to the key of node B with the same ordering applying across the heap. A heap can be classified further as either a “max heap” or a “min heap”.

You can see a max-heap representation below:

The main advantage of using a heap, is that we can keep our lists in a “semi-ordered” way. The idea behind the semi-ordered is that we can quickly reorder the heap (a method that is commonly called **Heapify**). How would our problem benefit from this data structure? Well, if we can keep all the lists in a semi-ordered manner in a min-heap, the we could take the minimum element in **O(1)** and re structure the tree in **O(log(K))**. This is a drastic win from our brute force approach which had to always go through all the lists and was going to take **O(K)** to get a single element! The rest of the algorithm to merge multiple sorted lists of strings should be approximately the same. So let us put our thoughts into more concise steps.

## Merge Multiple Sorted Lists of Strings – Heap Algorithm

- Put all the leasts in a min-heap.
- While the heap has still more elements.
- Pop the first minimum / top element and put it into a return list.

Sounds pretty straight forward? The data structure in Java that represents a Heap is a Priority Queue. So with that in mind let us go ahead and write some code.

### Merge Multiple Sorted Lists of Strings – Java Heap Implementation

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class Solution { public ArrayList<String> mergeMultipleLists(ArrayList<ArrayList<String>> stringLists) { PriorityQueue<ArrayList<String>> queue = new PriorityQueue<ArrayList<String>>( stringLists.size(), new Compartor <ArrayList<String>>() { @Override public int compare (ArrayList<String> firstList, ArrayList<String> secondList) { return firstList.get(0).compareTo(secondList.get(0); } } for (int i = 0; i < stringLists.size(); i++) { queue.add(stringLists.get(i)); } ArrayList<String> finalSortedArray = new ArrayList<String>(); while (!queue.isEmpty()) { finalSortedArray.add(queue.poll()); } return finalSortedArray; } |

I will leave you as a homework to think through the space and complexity of this one too :). Although we did get an idea on the algorithm build up.

I think this is pretty much all there is to this question. The heap solution is slightly trickier to get to, but you might be able to earn some brownie points in an interview if you mention and implement it. The first two solutions should be doable by anyone that has encountered Merge Sort before.

Hope you guys enjoyed it… and I’ll see you guys next time! ;D

#### Latest posts by Ajk (see all)

- Find Median from Numbers Array - January 1, 2018
- Find Whether a Number Can Be the Sum of Two Squares - August 12, 2017
- How to Find Two Primes Whose Sum is Equal to a Number N - April 22, 2017