Merge k Sorted Lists

medium Java Collections

Problem

Every input line is one list of integers, already sorted from small to big. Merge all lines into one sorted list and print it, numbers separated by spaces.

Constraints

  • 1 <= k <= 100
  • |value| <= 10^9
  • each line is sorted and not empty

Examples

Input

1 4 5
1 3 4
2 6

Output

1 1 2 3 4 4 5 6

Solutions

Best approachTime O(N log k)Space O(k)

The heap always holds the front number of every list. The smallest one is the next answer, and its list supplies the next candidate. For N numbers in total the cost is O(N log k).

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : The merged list.
 * Approach: Heap.
 * Time    : O(N log k)
 * Space   : O(k)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String solve(String[] lines) {
        // Step 1: Read the lists. The heap holds {value, list number, position}. It always gives the smallest value of the front numbers.
        int k = lines.length;
        long[][] lists = new long[k][];
        java.util.PriorityQueue<long[]> heap = new java.util.PriorityQueue<long[]>((x, y) -> Long.compare(x[0], y[0]));
        for (int i = 0; i < k; i++) {
            String[] part = lines[i].split(" ");
            lists[i] = new long[part.length];
            for (int j = 0; j < part.length; j++) {
                lists[i][j] = Long.parseLong(part[j]);
            }
            heap.add(new long[] {lists[i][0], i, 0});
        }
        // Step 2: Take the smallest, write it, and push the next number of the same list.
        StringBuilder result = new StringBuilder();
        while (!heap.isEmpty()) {
            long[] top = heap.poll();
            result.append(result.length() == 0 ? "" : " ").append(top[0]);
            int list = (int) top[1];
            int next = (int) top[2] + 1;
            if (next < lists[list].length) {
                heap.add(new long[] {lists[list][next], list, next});
            }
        }
        return result.toString();
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(solve(lines));
    }
}
Hints (2)
  1. How many items does the heap hold at most?
  2. What do we push after a pop?