Frontend Interview Handbook3 min read

Data Structures and Algorithms for Frontend Interviews

Data Structures And Algorithms For Frontend Interviews Guide

Generally speaking, most frontend interviews tend to focus more on frontend-oriented coding questions, such as building UI components, managing state, or working with APIs. That said, many top companies will still test your understanding of core data structures and algorithms. It’s always a good idea to brush up on the fundamentals, just in case.


Honest Advice on Data Structures and Algorithms for Frontend

Now, let me be honest with you for a second. From my own experience, both as someone who has been interviewed for over 13 years and as someone who has conducted numerous interviews myself, if a company is strictly asking LeetCode-style algorithm questions for a frontend role, that’s a red flag. It suggests that the company likely lacks the necessary competency and resources to evaluate frontend engineers properly. Solving a linked list reversal or inverting a binary tree is not a strong indicator of whether someone can build a scalable UI, understand browser behavior, or write maintainable frontend code.

With that being said, I still think it’s essential to have a high-level understanding of the significant data structures, not because you’ll be asked to implement them from scratch, but because knowing them will help you recognize patterns and think through problems efficiently.

I would focus on a few core concepts: stacks, sets, queues, and priority queues; some basic tree traversal logic; ES6 maps; and hash tables. Occasionally, you may encounter a TRIE-style question that relates to a frontend concept (such as memoization or autocomplete). However, I’ve rarely been asked to reverse a linked list or build a graph using adjacency lists. And if I am? I walk away. Not worth it.

Now, if you do want to brush up on these concepts, the best free tutorials out there are from a nonprofit called FreeCodeCamp. We’re not affiliated with them at FrontendLead.com, but their videos are solid and beginner-friendly. Below, you’ll find a high-level summary of each concept, a simple example, and a direct link to the in-depth video for each topic.

Table of Contents

  1. Stacks
  2. Sets
  3. Queues & Priority Queues
  4. Binary Search Trees
  5. BST Traversals & Height
  6. Maps & ES6 Map
  7. Hash Tables
  8. Linked List
  9. Trie
  10. Heap (Max & Min)
  11. Graph & Adjacency Lists
  12. Graph BFS

1. Stacks (Built from Scratch)

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. This means the last item added is the first one removed — like a stack of plates. Stacks are used in scenarios like undo/redo functionality, browser history, and tracking function calls.

class Stack {
  constructor() {
    this.items = []; // Internal array to hold elements
  }

  push(value) {
    // Add an element to the top of the stack
    this.items[this.items.length] = value;
  }

  pop() {
    // Return undefined if the stack is empty
    if (this.items.length === 0) return undefined;

    // Get the last item (top of stack)
    const last = this.items[this.items.length - 1];

    // Reduce the length of the array to remove it
    this.items.length = this.items.length - 1;

    // Return the removed value
    return last;
  }

  peek() {
    // Look at the top value without removing it
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    // Return true if no elements are in the stack
    return this.items.length === 0;
  }
}

// Example usage
const stack = new Stack();
stack.push(10); // [10]
stack.push(20); // [10, 20]
stack.pop();    // 20

Watch the Stacks video

2. Sets (Built from Scratch)

A set is a collection of unique values — no duplicates allowed. You can use sets when you need to filter out duplicates, quickly check membership, or store flags. JavaScript includes a built-in Set object, but here’s how to build one from scratch.

class MySet {
  constructor() {
    this.items = {}; // Use an object to store unique values as keys
  }

  add(value) {
    // Add the value as a key (won't allow duplicates)
    this.items[value] = true;
  }

  has(value) {
    // Return true if the key exists
    return this.items.hasOwnProperty(value);
  }

  delete(value) {
    // Remove the key from the object
    delete this.items[value];
  }

  values() {
    // Return an array of all stored keys
    return Object.keys(this.items);
  }
}

// Example usage
const set = new MySet();
set.add("apple");
set.add("apple"); // Duplicate won't be added
set.has("apple"); // true
set.delete("apple");

Watch the Sets video

3. Queues (Built from Scratch)

A queue is a data structure that follows the First In, First Out (FIFO) principle. This means the first item added is the first one removed — like people waiting in line. Queues are useful for scheduling tasks, animations, or buffering streams.

class Queue {
  constructor() {
    this.items = {};  // Object to hold the queue
    this.head = 0;    // Index of the front element
    this.tail = 0;    // Index of the next empty slot
  }

  enqueue(value) {
    // Add element at the tail index
    this.items[this.tail] = value;
    this.tail++;
  }

  dequeue() {
    // If queue is empty, return undefined
    if (this.head === this.tail) return undefined;

    // Get the front item
    const value = this.items[this.head];

    // Remove it from the object
    delete this.items[this.head];
    this.head++;

    // Return the dequeued value
    return value;
  }

  peek() {
    // Look at the front of the queue
    return this.items[this.head];
  }

  isEmpty() {
    // True if no elements left
    return this.head === this.tail;
  }
}

// Example usage
const queue = new Queue();
queue.enqueue("A");
queue.enqueue("B");
queue.dequeue(); // "A"

Watch the Queues video

4. Binary Search Tree (Built from Scratch)

A Binary Search Tree (BST) is a hierarchical data structure where each node has up to two children. The left child contains values less than the parent, and the right child contains values greater than the parent. BSTs allow fast lookup, insertion, and deletion — typically in O(log n) time. They’re useful in search-heavy applications and form the foundation for other advanced data structures.

class TreeNode {
  constructor(value) {
    this.value = value;      // The value stored in the node
    this.left = null;        // Left child
    this.right = null;       // Right child
  }
}

class BinarySearchTree {
  constructor() {
    this.root = null;        // Root of the tree
  }

  insert(value) {
    const newNode = new TreeNode(value);

    if (this.root === null) {
      // If tree is empty, set the new node as root
      this.root = newNode;
      return;
    }

    let current = this.root;

    while (true) {
      if (value < current.value) {
        // Go left
        if (current.left === null) {
          current.left = newNode;
          return;
        }
        current = current.left;
      } else {
        // Go right
        if (current.right === null) {
          current.right = newNode;
          return;
        }
        current = current.right;
      }
    }
  }

  find(value) {
    let current = this.root;

    while (current) {
      if (value === current.value) return true;
      current = value < current.value ? current.left : current.right;
    }

    return false;
  }
}

// Example usage
const bst = new BinarySearchTree();
bst.insert(10);
bst.insert(5);
bst.insert(15);
bst.find(15); // true
bst.find(7);  // false

Watch the BST video

5. BST Traversals & Height

Once you’ve built a tree, you’ll often want to traverse it — meaning visit each node in a specific order. The three main types of depth-first traversal are:

  • In-order (left → root → right)
  • Pre-order (root → left → right)
  • Post-order (left → right → root)

Additionally, calculating the height of a tree is useful for understanding its depth or balance.

class TreeTraversal {
  static inOrder(node, result = []) {
    if (!node) return result;
    TreeTraversal.inOrder(node.left, result);     // Traverse left subtree
    result.push(node.value);                      // Visit root
    TreeTraversal.inOrder(node.right, result);    // Traverse right subtree
    return result;
  }

  static preOrder(node, result = []) {
    if (!node) return result;
    result.push(node.value);                      // Visit root
    TreeTraversal.preOrder(node.left, result);    // Traverse left
    TreeTraversal.preOrder(node.right, result);   // Traverse right
    return result;
  }

  static postOrder(node, result = []) {
    if (!node) return result;
    TreeTraversal.postOrder(node.left, result);   // Traverse left
    TreeTraversal.postOrder(node.right, result);  // Traverse right
    result.push(node.value);                      // Visit root
    return result;
  }

  static height(node) {
    if (!node) return -1; // Height of empty tree is -1
    const leftHeight = TreeTraversal.height(node.left);
    const rightHeight = TreeTraversal.height(node.right);
    return 1 + Math.max(leftHeight, rightHeight); // 1 + taller side
  }
}

// Example usage
const exampleTree = new BinarySearchTree();
exampleTree.insert(10);
exampleTree.insert(5);
exampleTree.insert(15);
exampleTree.insert(2);
exampleTree.insert(7);

// Traversals
TreeTraversal.inOrder(exampleTree.root);    // [2, 5, 7, 10, 15]
TreeTraversal.preOrder(exampleTree.root); ... premium content.
Free account

Keep reading for free

Create a free account to finish this article and unlock every free resource for your frontend interview prep.

  • Full article access
  • Quizzes & study plans
  • No credit card
Sign up free

Already a member? Log in

4.9/5 from our users