Implement a stack (last-in, first-out) backed by a singly linked list, supporting:
push(x) — add x to the top.pop() — remove and return the top element; return -1 if the stack is empty.Both operations must be O(1). The first operation names the class (its constructor).
Input: push(5), push(10), pop(), pop(), pop() Output: 10, 5, -1 LIFO: the last pushed (10) is popped first, then 5, then -1.
Input: push(7), pop() Output: 7 Push 7, pop returns 7.
- 1 <= number of operations <= 100 - 1 <= x <= 10^5 - pop() returns -1 if the stack is empty.
A linked list gives O(1) insertion and removal at the head — which is exactly what a stack needs. Keep a head pointer that always points at the top: push prepends a new node, pop unlinks the head.
next pointer, chained together.“Which end is the top?”
The head of the list — both push and pop happen there.
“What does pop return when empty?”
-1, and the head is null.
I'll keep a head pointer that always points at the top of the stack.
Push creates a node whose next is the current head, then makes it the new head.
Pop reads the head's value and moves head to head.next, returning -1 if head is null.
Worked example — push 5, push 10, pop, pop, pop
push 5 -> head -> [5] (null) push 10 -> head -> [10] -> [5] (null) pop -> head -> [5] returns 10 pop -> head -> null returns 5 pop -> head is null returns -1
Prepending and unlinking at the head of a singly linked list need no traversal, giving O(1) push and pop.
Unlike an array-backed stack, a linked list grows one node at a time — there's no resizing and no wasted capacity.
Key takeaway
Keep a head that points at the top. push prepends a node (new head); pop returns the head's value and advances head, or -1 when the list is empty. Every operation is O(1) with no resizing.
push(x): head = Node(x, next=head) pop(): return -1 if head is null; val = head.val; head = head.next; return val