Topicsβ€ΊStackβ€ΊDesign Stack
πŸ“–

Design Stack

Stack
~20 min read
5 practice problems

Overview

Design stack: implement a stack with given operations, typically push, pop, top, and often getMin (or getMax), all O(1) amortized or worst-case. Use an array (push/pop at end) or a linked list (top = head). For getMin, use an auxiliary Min Stack or store (value, minSoFar) in each node.


When to Use

  • Stack + getMin/getMax β€” min stack or (val, min) pairs.
  • Stack with O(1) everything β€” array or linked list; no extra ops.
  • Foundation for Min Stack, Queue using Stacks.

How It Works

Storage: array (stack.push/pop) or linked list (insert/remove at head). getMin: either a second stack that stays non-increasing, or each element stores (value, minWhenPushed). getMax: same with non-decreasing stack or (value, maxWhenPushed).


Example 1: Basic Stack (Array)

class MyStack {
  private arr: number[] = [];
  push(x: number): void { this.arr.push(x); }
  pop(): number { return this.arr.pop()!; }
  top(): number { return this.arr[this.arr.length - 1]; }
  empty(): boolean { return this.arr.length === 0; }
}

All O(1).


Example 2: Stack with getMin (Auxiliary Stack)

class MinStack {
  private stack: number[] = [];
  private minStack: number[] = [];
  push(val: number): void {
    this.stack.push(val);
    if (this.minStack.length === 0 || val <= this.minStack[this.minStack.length - 1])
      this.minStack.push(val);
  }
  pop(): void {
    const x = this.stack.pop()!;
    if (this.minStack[this.minStack.length - 1] === x) this.minStack.pop();
  }
  top(): number { return this.stack[this.stack.length - 1]; }
  getMin(): number { return this.minStack[this.minStack.length - 1]; }
}

See Min Stack for details.


Example 3: Stack with getMin (Store Pair)

Each node stores (value, minSoFar). Push: minSoFar = min(val, top.minSoFar or val). getMin = top.minSoFar. No second stack; O(1) extra space per element.

class MinStackPair {
  private stack: [number, number][] = [];
  push(val: number): void {
    const min = this.stack.length === 0 ? val : Math.min(this.stack[this.stack.length - 1][1], val);
    this.stack.push([val, min]);
  }
  pop(): void { this.stack.pop(); }
  top(): number { return this.stack[this.stack.length - 1][0]; }
  getMin(): number { return this.stack[this.stack.length - 1][1]; }
}

Example 4: Stack with Linked List

Top = head. Push: new node, next = head, head = new. Pop: val = head.val, head = head.next, return val. O(1) per op; no array resize.

class Node { constructor(public val: number, public next: Node | null) {} }
class StackLL {
  private head: Node | null = null;
  push(x: number): void { this.head = new Node(x, this.head); }
  pop(): number { const v = this.head!.val; this.head = this.head!.next; return v; }
  top(): number { return this.head!.val; }
  empty(): boolean { return this.head === null; }
}

Example 5: Edge Cases and Variants

  • Empty pop/top: document or throw; or return -1.
  • getMax: same as getMin with max stack (non-decreasing) or (val, maxSoFar).
  • Capacity: array stack can grow; linked list has no fixed cap. Specify if problem asks for fixed size.

Summary

  • Design stack: array or linked list for push/pop/top; getMin via Min Stack or (value, minSoFar) pairs. See Stack Basics.