BackmediumStackAdobe

Galactic Supply Chain Management Solution

Problem Statement

You are given a sequence of stack commands. The first line contains an integer N, the number of commands (1 ≤ N ≤ 2·10^5). Each of the next N lines is either "PUSH x" where x is a 32‑bit signed integer, or "POP". Begin with an empty integer stack. Execute the commands in order: "PUSH x" pushes x onto the top of the stack, "POP" removes the top element if the stack is non‑empty and does nothing otherwise. After all commands have been processed, output the remaining stack contents from bottom to top separated by a single space. If the stack is empty, output the word "EMPTY".

Example 1
Input
5 PUSH 3 PUSH 5 POP PUSH 2 POP
Output
3

Explanation: Start empty. PUSH 3 → [3]. PUSH 5 → [3,5]. POP removes 5 → [3]. PUSH 2 → [3,2]. POP removes 2 → [3]. Final stack is [3]; output "3".

Example 2
Input
4 POP PUSH -1 PUSH 10 POP
Output
-1

Explanation: POP on empty stack is ignored. PUSH -1 → [-1]. PUSH 10 → [-1,10]. POP removes 10 → [-1]. Final stack is [-1]; output "-1".

Example 3
Input
6 PUSH 7 PUSH 8 PUSH 9 POP POP POP
Output
EMPTY

Explanation: Push 7,8,9 → [7,8,9]. Three POPs remove 9, then 8, then 7, leaving the stack empty. Output "EMPTY".

Constraints

  • 1 <= N <= 200000
  • -2147483648 <= x <= 2147483647
  • All operations are either "PUSH x" or "POP
Live Compiler1 Free Run Available
Loading Editor...
Test Cases & Output
Click "Run" to test your 1 free compile trial!

🚀 Practice this problem

Run code, get AI hints & track streak

Sign Up Free

Galactic Supply Chain Management — Problem Statement & Solution Guide

StackMediumMixed
TimeO(N)
|
SpaceO(N)

Problem Description

You are given a sequence of stack commands. The first line contains an integer N, the number of commands (1 ≤ N ≤ 2·10^5). Each of the next N lines is either "PUSH x" where x is a 32‑bit signed integer, or "POP". Begin with an empty integer stack. Execute the commands in order: "PUSH x" pushes x onto the top of the stack, "POP" removes the top element if the stack is non‑empty and does nothing otherwise. After all commands have been processed, output the remaining stack contents from bottom to top separated by a single space. If the stack is empty, output the word "EMPTY".

DSA Pattern Breakdown

DSA Pattern Breakdown

"Galactic Supply Chain Management"

medium

WHY DOES IT MATTER?

The stack pattern is essential for problems involving backtracking, expression evaluation, and nested structures. It provides a simple yet powerful mechanism to manage state in a way that is easily reversible, making it a cornerstone of algorithmic design for medium-difficulty problems that require tracking the 'current' context while preserving history.

OPTIMIZATION CHALLENGE

The key insight is to use a dynamic array (or a pre-allocated array with a size limit) rather than a linked list for the stack implementation. While a linked list offers O(1) push/pop, it has poor cache locality and higher memory overhead per node. A dynamic array leverages CPU cache efficiency, making it significantly faster in practice for large N, despite the theoretical O(1) amortized cost of resizing.

REAL-WORLD CONNECTION

This pattern is directly analogous to a warehouse inventory system where items are stacked on a pallet. The most recently delivered item is the first to be picked for shipment. In distributed systems, it also resembles the management of transaction logs or message queues where the latest event is the most relevant for immediate processing, while older events remain available for audit or rollback.

During the interview, explicitly mention that you are using an array-based stack for cache efficiency. Also, clarify the behavior of POP on an empty stack (no-op vs. error) to demonstrate awareness of edge cases and system robustness. This shows you think beyond just the algorithm to the practical implications of the code.

COMPLEXITY AT A GLANCE

⏱ Time:O(N)
💾 Space:O(N)

Core Theory — Why This Approach?

The problem models a Last-In-First-Out (LIFO) data structure, specifically a stack, which is fundamental in computer science for managing execution contexts, memory allocation, and undo mechanisms. The core theoretical challenge lies in handling a high volume of operations (up to 2·10^5) efficiently. While the logical operation of pushing or popping an element is conceptually trivial, the physical implementation must guarantee constant-time access to the top element and efficient memory management to prevent performance degradation under load. The optimal paradigm relies on the dynamic array-based stack implementation, where elements are stored in a contiguous block of memory, allowing O(1) amortized time complexity for both push and pop operations by simply adjusting a pointer (or index) to the top of the stack.

Interview Questions on This Problem

Q1How would you handle a scenario where the input stream contains more POP commands than PUSH commands, and why is this distinction important for system stability?

In a robust system, a POP command on an empty stack should be a no-op (do nothing) rather than causing an exception or crash. This is crucial for fault tolerance in distributed systems where message ordering might be disrupted or where redundant cleanup signals are sent. In the context of this problem, explicitly checking if the stack is non-empty before performing a pop prevents undefined behavior and ensures the program continues to process subsequent commands correctly.

Q2If we were to extend this problem to support a 'PEEK' operation that returns the top element without removing it, how would the time and space complexity change, and what are the implications for a real-time monitoring system?

The time complexity remains O(1) for the PEEK operation as it only requires accessing the element at the current top index without modifying the stack pointer. The space complexity remains O(N) where N is the maximum number of elements in the stack at any point. In a real-time monitoring system, this allows for non-destructive inspection of the current state (e.g., checking the latest sensor reading) without altering the historical data, which is essential for debugging and state verification.

Q3Why is a stack preferred over a queue for managing function call frames in a programming language runtime, and how does this relate to the 'Galactic Supply Chain' analogy?

A stack is preferred because function calls are nested; the most recent function call must be the first to finish and return control to the caller (LIFO). This mirrors the 'Galactic Supply Chain' where the most recently added supply item (top of the stack) is the first to be processed or removed. Using a queue (FIFO) would violate the logical dependency of nested operations, leading to incorrect execution flow and state corruption.

Examples

Example 1

Input

5
PUSH 3
PUSH 5
POP
PUSH 2
POP

Output

3

Explanation: Start empty. PUSH 3 → [3]. PUSH 5 → [3,5]. POP removes 5 → [3]. PUSH 2 → [3,2]. POP removes 2 → [3]. Final stack is [3]; output "3".

Example 2

Input

4
POP
PUSH -1
PUSH 10
POP

Output

-1

Explanation: POP on empty stack is ignored. PUSH -1 → [-1]. PUSH 10 → [-1,10]. POP removes 10 → [-1]. Final stack is [-1]; output "-1".

Example 3

Input

6
PUSH 7
PUSH 8
PUSH 9
POP
POP
POP

Output

EMPTY

Explanation: Push 7,8,9 → [7,8,9]. Three POPs remove 9, then 8, then 7, leaving the stack empty. Output "EMPTY".

Constraints

  • 1 <= N <= 200000
  • -2147483648 <= x <= 2147483647
  • All operations are either "PUSH x" or "POP

Optimal Approach & Strategy

Use a dynamic array (list) to represent the stack, where the last element is the top. For each command, perform a direct append or pop operation on the array, ensuring O(1) amortized time complexity. This leverages the contiguous memory layout of arrays for optimal cache performance.

Brute Force Approach

A naive approach might involve using a linked list or a list where we search for the top element, but this is unnecessary overhead. Alternatively, one might try to simulate the stack using a string buffer, which is inefficient and prone to parsing errors.

Verified Code Solutions

JavaScript Solution
Time: O(N)
const fs = require('fs');
const data = fs.readFileSync(0,'utf8').trim().split(/\s+/);
let pos = 0;
const N = parseInt(data[pos++]);
const stack = [];
for(let i=0;i<N;i++){
  const cmd = data[pos++];
  if(cmd==='PUSH'){
    const x = parseInt(data[pos++]);
    stack.push(x);
  }else if(cmd==='POP'){
    if(stack.length) stack.pop();
  }
}
if(stack.length===0) console.log('EMPTY');
else console.log(stack[stack.length-1]);

Asked in Top Tech Interviews

Adobe

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.