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
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).
/*
* 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)
- Why does pop move the last element to the root?