Priority Crate Management — Problem Statement & Solution Guide

ArraysMediumStack LIFO
TimeO(1)
|
SpaceO(C)

Quick Answer & Algorithm Key Takeaway

Master coding challenges related to Arrays and solve the Priority Crate Management problem optimally.

TopicArrays
PatternStack LIFO
TimeO(1)
SpaceO(C)

Problem Description

Design a class named CrateManager that simulates a fixed-capacity storage system for integer identifiers using a Last-In-First-Out (LIFO) strategy. The system must strictly enforce capacity limits and provide atomic operations for managing the stack of crates. The class must be initialized with a specific maximum capacity and must handle overflow conditions gracefully without throwing exceptions for standard operations, returning a boolean status instead.

Implement the following methods:

1. push(value: int) -> bool: Inserts a new crate identifier onto the top of the stack. Returns true if the insertion was successful, or false if the stack is already at full capacity.

2. pop() -> int: Removes and returns the identifier of the top crate. If the stack is empty, return -1.

3. top() -> int: Returns the identifier of the top crate without removing it. If the stack is empty, return -1.

4. isEmpty() -> bool: Returns true if the stack contains no crates, otherwise false.

5. isFull() -> bool: Returns true if the stack has reached its maximum capacity, otherwise false.

The implementation must ensure O(1) time complexity for all operations. The underlying data structure should be an array of size equal to the capacity, with a pointer tracking the current top index to facilitate constant-time access and modification.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Priority Crate Management"

medium

WHY DOES IT MATTER?

The bounded‑stack pattern enforces resource limits, prevents runaway memory growth, and provides predictable O(1) operation latency—critical for systems with hard real‑time constraints or strict SLA budgets.

OPTIMIZATION CHALLENGE

The key insight is to avoid dynamic resizing or pointer chasing by pre‑allocating the storage and using a single integer as a cursor; this reduces both time overhead (no allocation) and space overhead (no extra node objects).

REAL-WORLD CONNECTION

Think of a warehouse loading dock that can hold only a fixed number of pallets; each new pallet must replace the most recently placed one only if space exists, mirroring the LIFO and capacity checks of a bounded stack.

During an interview, write the push/pop logic first, then immediately add the capacity guard; a one‑line guard (if(top+1==cap) return false;) shows you respect constraints before worrying about edge‑case returns.

COMPLEXITY AT A GLANCE

⏱ Time:O(1)
💾 Space:O(C)

Core Theory — Why This Approach?

A stack is a linear data structure that follows the Last‑In‑First‑Out (LIFO) discipline. By storing crate identifiers in a contiguous array and maintaining a single index (the "top"), each push or pop can be performed in constant time without traversing the structure. Naïve solutions that use dynamic containers (e.g., std::vector push_back with automatic resizing or linked‑list insert at head) either violate the fixed‑capacity contract or incur hidden amortized costs, which become problematic when the system must guarantee strict capacity limits and deterministic latency—requirements common in embedded or high‑frequency trading environments. The optimal paradigm therefore couples a pre‑allocated array of size C (the maximum capacity) with a simple integer pointer, ensuring O(1) time, O(C) space, and deterministic behavior even under extreme load.

Interview Questions on This Problem

Q1How would you implement a fixed‑capacity stack that returns a status instead of throwing on overflow/underflow?

Allocate an array of size capacity, keep an integer top initialized to ‑1; on push, check if top+1==capacity and return false if so, otherwise increment top and store the value; on pop, check if top==-1 and return false, otherwise retrieve array[top] and decrement top.

Q2What modifications are needed to make CrateManager thread‑safe for concurrent push/pop operations?

Wrap push and pop in a mutex (or use atomic compare‑and‑swap on the top index) so that only one thread can modify the top pointer at a time; optionally use a lock‑free ring‑buffer style algorithm if high contention is expected.

Q3Why might a naïve linked‑list implementation be rejected for a high‑throughput fintech system that requires a bounded stack?

A linked list allocates a node per push, leading to unpredictable memory allocation latency and no inherent capacity bound; this can cause GC pauses or memory fragmentation, violating the deterministic latency and strict capacity guarantees required in fintech trading pipelines.

Examples

Example 1

Input

CrateManager cm = new CrateManager(3);
cm.push(10);
cm.push(20);
cm.push(30);
cm.isFull();
cm.push(40);
cm.top();
cm.pop();
cm.top();

Output

true
false
30
30
20

Explanation: 1. Initialize manager with capacity 3. 2. Push 10: Stack is [10], returns true. 3. Push 20: Stack is [10, 20], returns true. 4. Push 30: Stack is [10, 20, 30], returns true. 5. isFull(): Stack size is 3, capacity is 3, returns true. 6. Push 40: Stack is full, returns false. Stack remains [10, 20, 30]. 7. top(): Top element is 30, returns 30. 8. pop(): Removes 30, returns 30. Stack is now [10, 20]. 9. top(): Top element is now 20, returns 20.

Example 2

Input

CrateManager cm = new CrateManager(2);
cm.pop();
cm.top();
cm.push(5);
cm.isEmpty();
cm.push(7);
cm.pop();
cm.pop();

Output

-1
-1
true
false
7
5
-1

Explanation: 1. Initialize manager with capacity 2. 2. pop(): Stack is empty, returns -1. 3. top(): Stack is empty, returns -1. 4. push(5): Stack is [5], returns true. 5. isEmpty(): Stack has 1 element, returns false. 6. push(7): Stack is [5, 7], returns true. 7. pop(): Removes 7, returns 7. Stack is [5]. 8. pop(): Removes 5, returns 5. Stack is empty.

Example 3

Input

CrateManager cm = new CrateManager(1);
cm.push(100);
cm.push(200);
cm.top();
cm.pop();
cm.push(300);
cm.top();

Output

true
false
100
100
true
300

Explanation: 1. Initialize manager with capacity 1. 2. push(100): Stack is [100], returns true. 3. push(200): Stack is full, returns false. Stack remains [100]. 4. top(): Top element is 100, returns 100. 5. pop(): Removes 100, returns 100. Stack is empty. 6. push(300): Stack is [300], returns true. 7. top(): Top element is 300, returns 300.

Constraints

  • 1 <= capacity <= 10^5
  • 0 <= value <= 10^9
  • At most 10^5 calls will be made to push, pop, top, isEmpty, and isFull.
  • The stack must be implemented using an array of size equal to the capacity.

Optimal Approach & Strategy

Pre‑allocate an array of the given capacity and maintain a top index; push/pop become simple index updates with constant‑time bounds checks.

Brute Force Approach

Use a dynamic list and on each push check length, resizing if needed; on pop remove the last element, which may involve shifting or reallocation.

Code Solutions

JavaScript Solution
Time: O(1)
class CrateManager {
    constructor(capacity) {
        this.capacity = capacity;
        this.stack = [];
    }
    push(crate) {
        if (this.stack.length < this.capacity) this.stack.push(crate);
    }
    pop() {
        if (this.stack.length === 0) return -1;
        return this.stack.pop();
    }
    top() {
        if (this.stack.length === 0) return -1;
        return this.stack[this.stack.length - 1];
    }
    isFull() {
        return this.stack.length === this.capacity;
    }
    isEmpty() {
        return this.stack.length === 0;
    }
}

const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false });
let cm = null;
rl.on('line', (line) => {
    const parts = line.trim().split(/\s+/);
    const cmd = parts[0];
    if (cmd === 'new') {
        cm = new CrateManager(parseInt(parts[1], 10));
    } else if (cmd === 'push') {
        cm.push(parseInt(parts[1], 10));
    } else if (cmd === 'pop') {
        console.log(cm.pop());
    } else if (cmd === 'top') {
        console.log(cm.top());
    } else if (cmd === 'full') {
        console.log(cm.isFull() ? 'true' : 'false');
    } else if (cmd === 'empty') {
        console.log(cm.isEmpty() ? 'true' : 'false');
    }
});

Asked in Top Tech Interviews

Razorpay

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.