Min-Heap Priority Queue

Problem

Build a min-heap yourself (an array where the smallest number is at index 0; do not use a ready-made priority queue). Commands: push x, pop (print the smallest number and remove it, or empty), peek (print the smallest or empty) and size (print how many numbers are in the heap). push prints nothing.

Constraints

  • 1 <= commands <= 10^5
  • |x| <= 10^9

Examples

Input

push 5
push 3
peek
pop
size

Output

3
3
1

Solutions

Best approachTime O(n log n)Space O(n)

A heap keeps only a weak order (parent <= children), which is cheaper to maintain than a fully sorted list: push and pop cost O(log n), peek costs O(1). Ready-made versions are PriorityQueue (Java) and heapq (Python).

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : One result per query command.
 * Approach: Array heap.
 * Time    : O(n log n)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: A binary heap lives in an array. The children of index i are at 2i + 1 and 2i + 2.
        static class MinHeap {
            private long[] items = new long[16];
            private int size = 0;

            int size() {
                return size;
            }

            long peek() {
                return items[0];
            }

            // Step 2: push adds the number at the end and moves it up while it is smaller than its parent.
            void push(long value) {
                if (size == items.length) {
                    items = java.util.Arrays.copyOf(items, size * 2);
                }
                int index = size++;
                items[index] = value;
                while (index > 0 && items[(index - 1) / 2] > items[index]) {
                    swap(index, (index - 1) / 2);
                    index = (index - 1) / 2;
                }
            }

            // Step 3: pop takes the root, puts the last number there and moves it down to its place.
            long pop() {
                long smallest = items[0];
                items[0] = items[--size];
                int index = 0;
                while (true) {
                    int left = 2 * index + 1;
                    int right = left + 1;
                    int best = index;
                    if (left < size && items[left] < items[best]) {
                        best = left;
                    }
                    if (right < size && items[right] < items[best]) {
                        best = right;
                    }
                    if (best == index) {
                        break;
                    }
                    swap(index, best);
                    index = best;
                }
                return smallest;
            }

            private void swap(int i, int j) {
                long temporary = items[i];
                items[i] = items[j];
                items[j] = temporary;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        MinHeap heap = new MinHeap();
        java.util.List<String> output = new java.util.ArrayList<>();
        for (String line : lines) {
            String[] part = line.split(" ");
            if (part[0].equals("push")) {
                heap.push(Long.parseLong(part[1]));
            } else if (part[0].equals("pop")) {
                output.add(heap.size() == 0 ? "empty" : String.valueOf(heap.pop()));
            } else if (part[0].equals("peek")) {
                output.add(heap.size() == 0 ? "empty" : String.valueOf(heap.peek()));
            } else {
                output.add(String.valueOf(heap.size()));
            }
        }
        return output.toArray(new String[0]);
    }

    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(String.join("\n", solve(lines)));
    }
}
Hints (1)
  1. Why does pop move the last element to the root?