Stacks Explained: A Key Data Structure for Problem Solving

Nitin SinghNitin Singh
6 min read

๐Ÿฅž Understanding Stacks in Data Structures

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. Think of it like a stack of plates: the last plate placed on top is the first one you remove.


๐Ÿง  Core Concepts

  • LIFO: Last inserted element is the first to be removed.

  • Operations:

    • push(): Add an element to the top.

    • pop(): Remove the top element.

    • peek(): View the top element without removing it.

    • isEmpty(): Check if the stack is empty.


๐Ÿ” Core Concepts with Code Samples

We'll use a stack implemented using arrays/lists for simplicity.

โœ… Java Code Example

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();

        // Push
        stack.push(10);
        stack.push(20);

        // Peek
        System.out.println("Top element: " + stack.peek()); // 20

        // Pop
        stack.pop();

        // isEmpty
        System.out.println("Is stack empty? " + stack.isEmpty()); // false
    }
}

โœ… Python Code Example

stack = []

# Push
stack.append(10)
stack.append(20)

# Peek
print("Top element:", stack[-1])  # 20

# Pop
stack.pop()

# isEmpty
print("Is stack empty?", len(stack) == 0)  # False

โœ… C++ Code Example

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> stk;

    // Push
    stk.push(10);
    stk.push(20);

    // Peek
    cout << "Top element: " << stk.top() << endl;  // 20

    // Pop
    stk.pop();

    // isEmpty
    cout << "Is stack empty? " << (stk.empty() ? "Yes" : "No") << endl;  // No

    return 0;
}

๐Ÿงฎ Stack Operations & Time Complexity

OperationTime Complexity
Push (Insert)O(1)
Pop (Delete)O(1)
Peek/TopO(1)
SearchO(n)

Stacks are generally implemented using arrays or linked lists. Most programming languages provide built-in stack libraries (like Stack in Java, or deque in Python).


๐Ÿ”„ Memory Layout (Deep Dive)

The internal memory layout of a stack depends on how itโ€™s implemented โ€” either using an array or a linked list. Both differ significantly in how they allocate memory and manage elements.

1. ๐Ÿงฑ Array-Based Stack Implementation (Contiguous Memory)

Memory Type: Contiguous (like an array)
Internal Structure: Java array
Behavior:

  • A fixed-size array is created

  • A top index keeps track of the last element

  • Push/pop happen at the same end

โœ… Java Example:

class StackArray {
    int[] stack;
    int top;

    StackArray(int size) {
        stack = new int[size];
        top = -1;
    }

    void push(int value) {
        if (top == stack.length - 1) {
            throw new RuntimeException("Stack Overflow");
        }
        stack[++top] = value;
    }

    int pop() {
        if (top == -1) {
            throw new RuntimeException("Stack Underflow");
        }
        return stack[top--];
    }
}

๐Ÿ“Š Memory Layout:

Index:   0   1   2   3   4
Value:  [ ] [ ] [30][40][50]
Top โ†’                โ†‘
  • All elements are in contiguous blocks of memory

  • Efficient for CPU caching

โœ… In Java, using ArrayList is a common choice when you want dynamic behavior without managing resizing yourself.


2. ๐Ÿ”— Linked List-Based Stack Implementation (Dynamic Memory)

Memory Type: Dynamic (heap)
Internal Structure: Linked list nodes
Behavior:

  • Each node contains a value and a pointer to the next node

  • The top refers to the head of the list

โœ… Java Example:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

class StackLinkedList {
    Node top;

    void push(int value) {
        Node node = new Node(value);
        node.next = top;
        top = node;
    }

    int pop() {
        if (top == null) {
            throw new RuntimeException("Stack Underflow");
        }
        int val = top.data;
        top = top.next;
        return val;
    }
}

๐Ÿ“Š Memory Layout:

[top] -> [50 | โ†’] -> [40 | โ†’] -> [30 | โ†’ null]

Nodes are scattered in memory

  • Each stores a value and a reference

  • Slightly more overhead due to object and pointer storage

๐Ÿ†š Side-by-Side Summary

FeatureArray StackLinked List Stack
Memory TypeContiguousDynamic (Heap)
Size FlexibilityFixedFlexible
Overflow RiskYesNo (until memory is full)
Access SpeedFast (due to locality)Slightly slower
Extra MemoryNoYes (for next pointers)
ImplementationSimpleSlightly complex

๐Ÿ’ก Interview Tip:
Sometimes you're asked to implement a stack using two queues โ€” a great way to test your grasp of queue and stack behavior.
๐Ÿ‘‰ If you'd like a dedicated blog post explaining this in detail with Java code, drop a comment and let me know!


๐Ÿ›  Real-World Analogy

Imagine a pile of books on a table. You can only take the top one off or add a new one on top โ€” just like a stack.


๐Ÿงฉ Common Stack Use Cases

  • Undo/Redo in text editors

  • Backtracking in games and algorithms

  • Function call stacks in programming languages

  • Balanced Parentheses and expression evaluation

  • Depth First Search (DFS) in graphs and trees


๐Ÿ“˜ LeetCode Practice Problems

Click to open and solve directly:


๐ŸŽฏ Tips for Interview Prep

Mastering stack-based problems requires a solid grip on both implementation details and recognizing when a stack is the ideal data structure. Here are some focused tips to help you stand out during interviews:

  • โœ… Pattern Recognition: Many stack problems revolve around these classic patterns:

    • Balancing symbols (e.g., parentheses, brackets)

    • Next greater/smaller element

    • Monotonic stack (increasing/decreasing sequences)

    • Reverse Polish Notation (RPN) evaluations

    • Backtracking or undo operations

  • โœ… Corner Cases to Consider:

    • Pushing/popping from an empty stack

    • Dealing with duplicate or invalid inputs (especially in RPN or parentheses)

    • Implementing getMin() in O(1) time

    • Edge behavior for temperature/stock span type questions (e.g., single-day input)

  • โœ… Code Neatness Matters:

    • Prefer meaningful variable names like stack, top, index, result

    • Avoid hardcoding valuesโ€”make your code adaptable

    • Write modular functions if time permits (like isValid(), calculate())

  • โœ… Space vs Time Trade-offs:

    • Be ready to explain your reasoning if using extra stacks (e.g., for Min Stack)

    • Always highlight if your solution uses O(n) space or if it's optimized

  • โœ… Dry Run During the Interview:

    • Walk through your solution out loud using a small input

    • Highlight how the stack evolves step-by-stepโ€”interviewers love clarity

  • ๐Ÿ’ฌ Pro Tip: Interviewers often ask "Can you implement a stack using queues?"
    Mention that it's a classic variation and say:
    โ€œIf you're interested in a detailed breakdown of this, let me know in the comments and Iโ€™ll write a separate post!โ€


๐Ÿ™Œ Wrapping Up

Stacks may seem simple at first glance, but they form the backbone of many powerful algorithms and real-world applications. Whether it's balancing expressions, navigating through browser history, or parsing code โ€” stack-based thinking is everywhere in software development.

I hope this post helped solidify your understanding of stacks and how they show up in coding interviews. If you have questions, feedback, or suggestions, feel free to drop a comment โ€” Iโ€™d love to hear from you!

๐Ÿ“ฌ Stay updated: More deep-dive posts on data structures are coming soon.
๐Ÿ‘‰ Subscribe to my blog and follow me on LinkedIn to never miss an update.


0
Subscribe to my newsletter

Read articles from Nitin Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nitin Singh
Nitin Singh

I'm a passionate Software Engineer with over 12 years of experience working with leading MNCs and big tech companies. I specialize in Java, microservices, system design, data structures, problem solving, and distributed systems. Through this blog, I share my learnings, real-world engineering challenges, and insights into building scalable, maintainable backend systems. Whether itโ€™s Java internals, cloud-native architecture, or system design patterns, my goal is to help engineers grow through practical, experience-backed content.