Antwa CodeAntwaCode Blog

Awesome Repo15 min read

JavaScript Algorithms: Patterns & Data Structures for Developers

Collection of algorithms and data structures in JavaScript.

Read in Bahasa Indonesia

JavaScript Algorithms and Data Structures is one of the most popular GitHub repositories for learning algorithms and data structures — and it's all written in JavaScript. Created by Oleksii Trekhleb, this repo has over 196,000 stars and more than 31,000 forks. If you want to learn computer science practically without wading through dense textbooks, this is the place to start.

JavaScript Algorithms Repository Image: GitHub

Why Should You Learn Algorithms & Data Structures?

As developers, we often gravitate toward the latest framework or library. But without a solid understanding of algorithms and data structures, application performance can become a serious problem — especially as the data you handle grows.

Imagine you're building a search feature in your application. Using linear search on 100 items? Still fine. But what about 1 million items? That's where efficient algorithms become a lifesaver.

Learning algorithms is also a staple of technical interviews. Many major tech companies — Google, Meta, Amazon — still give algorithm-based coding challenges. If you're familiar with the concepts, interviews become much more manageable.

And just as important, understanding algorithms turns you into a better problem solver, not just a "Stack Overflow copy-paste specialist."

What's in This Repo?

The javascript-algorithms repo has two main sections: data structures and algorithms. Each item has its own README with a complete explanation, visual diagrams, and links to YouTube videos if you want to dive deeper.

Data Structures

Data structures are how we store and organize data in a computer. Choosing the right data structure can make our code dramatically faster and more efficient.

Beginner Level (B)

Here are the beginner-level data structures covered in this repo:

  • Linked List — A collection of connected nodes. Each node holds data and a pointer to the next node. Ideal for data that's frequently inserted or deleted in the middle. Unlike arrays that use index-based access, linked lists must be traversed from the beginning.

  • Doubly Linked List — A linked list variant accessible from both directions (forward and backward). More flexible but requires more memory since each node has two pointers.

  • Queue — A FIFO (First In, First Out) data structure. Think of a line at an ATM — whoever arrives first gets served first. Used in breadth-first search and task scheduling.

  • Stack — A LIFO (Last In, First Out) data structure. Like a stack of plates — the top one gets taken first. Used in function call stacks, undo/redo in editors, and balanced parentheses checkers.

  • Deque — A double-ended queue, accessible from both ends. Highly flexible since it can function as both a queue and a stack.

  • Hash Table — Key-value storage that enables super-fast lookups with O(1) time complexity in the best case. This is what makes JavaScript Objects and Maps so powerful.

  • Heap — A tree-based data structure that maintains either max or min properties. Max heap: parent is always greater than children. Min heap: the opposite. Important for priority queues and sorting algorithms like Heap Sort.

  • Priority Queue — Like a queue but each element has a priority. High-priority elements are served first, even if they arrived later. Used in Dijkstra's algorithm.

Advanced Level (A)

More challenging advanced data structures:

  • Trie — A special tree structure for storing strings. Each node represents a character. Frequently used in autocomplete, spell checkers, and search engines. Lookup is O(m) where m is the string length.

  • Tree — Several variants, all covered in this repo:

    • Binary Search Tree (BST) — Each node has at most 2 children; left child is smaller, right child is larger. Average lookup is O(log n).
    • AVL Tree — A self-balancing BST. Insert and delete are slower, but lookup is guaranteed O(log n).
    • Red-Black Tree — A more loosely balanced tree than AVL. Faster for insert/delete, but slightly slower for lookups.
    • Segment Tree — For range queries (e.g., sum from index 3 to 7). Extremely efficient for range query problems.
    • Fenwick Tree — Also known as Binary Indexed Tree. More compact than a segment tree but more limited in functionality.
  • Graph — Can be directed (one-way) or undirected (two-way). Can be weighted or unweighted. Represented as an adjacency matrix or adjacency list. Frequently used for modeling networks, maps, social networks, and dependency graphs.

  • Disjoint Set — Also known as union-find. Main operations: union (merge two sets) and find (check if two elements are in the same set). Useful for connected components and Kruskal's algorithm.

  • Bloom Filter — A probabilistic data structure that's super efficient for checking whether an element exists in a set. Trade-off: it can have false positives (says "exists" when it doesn't), but no false negatives. Used in databases and network routers.

  • LRU Cache — Least Recently Used cache. Stores the N most recently accessed items. When the cache is full, the least recently accessed item is evicted. Used in browser caching, CDNs, and databases.

Algorithms

The algorithms section of this repo is organized by topic and paradigm. There are a ton of categories covered:

Mathematics

This is the foundation of all algorithms. Math in programming is often overlooked but critically important:

  • Bit Manipulation — Direct operations at the bit level using AND, OR, XOR, NOT, and bit shift operators. Example: checking if a number is odd can be done with num & 1. Extremely efficient performance-wise.

  • Factorial, Fibonacci Number — Recursive and iterative implementations. The recursive version is easier to understand but can cause stack overflow. The iterative version is safer for large inputs.

  • Sieve of Eratosthenes — An efficient way to find prime numbers up to N. Time complexity O(N log log N). An ancient algorithm that's still relevant today.

  • Euclidean Algorithm — For finding the Greatest Common Divisor (GCD). An algorithm dating back to 300 BC that's still used in modern cryptography!

  • Pascal's Triangle — A triangular number structure widely used in combinatorics and probability.

  • Matrices — Matrix operations like multiplication, transpose, and inverse. Important in computer graphics and machine learning.

  • Discrete Fourier Transform — Transforms signals from the time domain to the frequency domain. Used in audio processing and image compression.

  • Square Root — Implementing square root without using Math.sqrt(). Interesting to study.

Sets

Algorithms that work with collections of elements:

  • Power Set — Finding all subsets of a set. If a set has n elements, the power set has 2^n subsets. Can be solved with iteration or backtracking.

  • Permutations and Combinations — Foundations of many combinatorics problems. Permutations care about order; combinations do not.

  • Knapsack Problem — A classic optimization problem: how to pack items with different weights and values into a bag to maximize total value. The dynamic programming solution is O(nW).

  • Longest Common Subsequence (LCS) — Finding the longest matching subsequence in two strings. Important in version control (Git uses this concept!) and text diff tools.

  • Maximum Subarray — Finding the subarray with the largest sum. Kadane's Algorithm solves this in O(n) — very efficient.

  • Combination Sum — Finding number combinations that sum to a target. Commonly appears in coding interviews.

Strings

Many real-world problems involve string manipulation:

  • Palindrome — Checking whether a string reads the same forward and backward. Can be solved with two pointers moving from the ends toward the center, or by reversing the string.

  • Levenshtein Distance — Measuring the similarity between two strings (edit distance). The minimum number of insert, delete, or replace operations needed. Used in spell checkers, autocorrect, and DNA sequence alignment.

  • KMP Algorithm (Knuth–Morris–Pratt) — Efficient O(n+m) pattern matching. Uses a prefix function to avoid unnecessary re-searching.

  • Rabin Karp — Pattern search using hashing. Great for finding multiple patterns at once in a single text.

  • Z Algorithm — Similar to KMP but simpler. Calculates the length of matching substrings from each position.

  • Regular Expression Matching — Implementing regex from scratch using dynamic programming. Understanding this helps you understand why regex can be slow in certain cases.

  • Hamming Distance — The number of positions that differ between two strings of equal length. Used in error detection and coding theory.

Searching

Fundamental search algorithms you need to understand:

  • Linear Search — Simple but O(n). Suitable for small datasets or unsorted data.

  • Binary Search — Much faster at O(log n), but requires sorted data. Each step eliminates half the data. Correct implementation requires careful attention to boundary conditions.

  • Jump Search — A compromise between linear and binary search. Jumps several steps, then does a linear search in the right block. O(√n).

  • Interpolation Search — A smarter variant of binary search for uniformly sorted data. Estimates position based on data distribution. Can achieve O(log log n) in the best case.

Sorting

This is one of the most frequently asked topics in interviews. Here's a complete comparison:

NameBestAverageWorstStable?
Bubble SortO(n)O(n²)O(n²)Yes
Selection SortO(n²)O(n²)O(n²)No
Insertion SortO(n)O(n²)O(n²)Yes
Heap SortO(n log n)O(n log n)O(n log n)No
Merge SortO(n log n)O(n log n)O(n log n)Yes
Quick SortO(n log n)O(n log n)O(n²)No
ShellsortO(n log n)Gap sequence dependentO(n(log n)²)No
Counting SortO(n+r)O(n+r)O(n+r)Yes
Radix SortO(n·k)O(n·k)O(n·k)Yes

Each sorting algorithm has different trade-offs. Quick Sort is generally fastest in practice, but Merge Sort is more stable. If you only have a small amount of data, Insertion Sort can actually be faster because its overhead is minimal.

The Quick Sort implementation in this repo is quite elegant: pick a pivot, partition the array, then recursively sort both halves.

Linked Lists

Specific algorithms for linked list traversal:

  • Straight Traversal — Traversing from head to tail. The basis for many linked list operations like searching and printing.

  • Reverse Traversal — Traversing from tail to head. Can be done with recursion or iteration using an extra pointer. Useful for printing a linked list in reverse.

Trees

Fundamental tree traversal algorithms:

  • Depth-First Search (DFS) — Exploring as deep as possible along one branch before backtracking. Can be preorder (root-left-right), inorder (left-root-right), or postorder (left-right-root).

  • Breadth-First Search (BFS) — Exploring level by level from the root. Uses a queue. Best for finding the nearest node from the root.

Graph

Graph algorithms are critical for applications involving networks or relationships:

  • DFS and BFS — Two main ways to traverse a graph. DFS uses a stack (recursive), BFS uses a queue.

  • Dijkstra — Finding the shortest path from one point to all other points. Time complexity O((V+E) log V) with a priority queue.

  • Bellman-Ford — Like Dijkstra but handles negative edges. Time complexity O(VE). Useful when negative costs exist.

  • Floyd-Warshall — Finding the shortest path between all pairs of points. O(V³) but simple to implement.

  • Prim's and Kruskal — For minimum spanning tree (MST). Prim starts from one point and grows outward; Kruskal starts from the lightest edge.

  • Topological Sorting — Sorting based on dependencies. Important in build systems, task schedulers, and course prerequisite planning.

  • Articulation Points and Bridges — Finding critical points/bridges whose removal disconnects the graph.

  • Strongly Connected Components — Subsets of a directed graph where every point can reach every other point.

  • Eulerian Path — A path that traverses every edge exactly once. Eulerian Circuit: a path that starts and ends at the same point.

  • Hamiltonian Cycle — A cycle that visits every point exactly once. A fascinating NP-complete problem.

Cryptography

Some simple encryption algorithms for learning cryptography concepts:

  • Caesar Cipher — The classic letter-shifting cipher from Roman times. Each letter is shifted N positions. Easy to break but great for understanding basic substitution ciphers.

  • Hill Cipher — Matrix-based encryption. More complex than Caesar Cipher and requires linear algebra knowledge.

  • Rail Fence Cipher — Zig-zag encryption. Write the message diagonally, read it horizontally. Simple but can make a message unreadable.

  • Polynomial Hash — A hashing technique that maps strings to numbers. Foundation of many string matching algorithms.

Machine Learning

Interestingly, this repo also includes simple ML algorithm implementations worth studying:

  • NanoNeuron — A minimalist neural network for understanding basic forward/backward propagation concepts. Just a few lines of code but teaches fundamental ML concepts.

  • k-NN (k-Nearest Neighbors) — Classification based on nearest neighbors. Simple but often effective. Great as a baseline classifier.

  • k-Means — Unsupervised clustering. Good for grouping data based on similarity. Iterative: assign clusters, update centroids, repeat until convergence.

Image Processing & Others

  • Seam Carving — A content-aware image resizing technique. Removes the path (seam) with the lowest energy from the image. Unlike regular cropping, it preserves important content.

  • Weighted Random — Generating random numbers with configurable probabilities. Useful for game mechanics and simulations.

  • Genetic Algorithm — An evolutionary algorithm for optimization. Inspired by Darwin's natural selection: survive, mutate, cross over.

Algorithm Paradigms

The repo also organizes algorithms by approach paradigm:

  • Brute Force — Try every possibility. Simple but can be extremely slow for large inputs. Good as a baseline for comparing optimizations. Examples: Linear Search, Rain Terraces, Travelling Salesman Problem.

  • Greedy — Pick the best option at each step without considering the future. Doesn't always produce optimal solutions but is fast and simple. Examples: Jump Game, Dijkstra, Prim's.

  • Divide and Conquer — Break the problem into smaller parts, solve each, then combine. Examples: Merge Sort, Binary Search, Tower of Hanoi, Quicksort.

  • Dynamic Programming — Store sub-problem results to avoid recalculating (memoization). Transforms exponential time into polynomial time. Examples: Fibonacci, Knapsack, LCS, Bellman-Ford.

  • Backtracking — Like brute force but smarter because it can "back up" when the current solution path doesn't look promising. Examples: N-Queens, Knight's Tour, Power Set, Hamiltonian Cycle.

  • Branch and Bound — Extends backtracking by adding bounds to prune unpromising branches. More efficient than pure backtracking.

How to Use This Repo

This repo is extremely easy to use. Clone, install, and you're off:

# Clone the repository
git clone https://github.com/trekhleb/javascript-algorithms.git
 
# Install dependencies
cd javascript-algorithms
npm install
 
# Run all tests (requires Node >= 22)
npm test
 
# Run tests for a specific algorithm
npm test -- 'LinkedList'
npm test -- 'MergeSort'
npm test -- 'Dijkstra'
 
# Check code quality with ESLint
npm run lint

Every algorithm has its own test file you can read to understand how it works. The tests also serve as great usage examples.

There's also a playground file at ./src/playground/playground.js where you can experiment. Just write code, run the tests, and see the results:

# Test the playground
npm test -- 'playground'

If you run into issues, try deleting node_modules and reinstalling:

rm -rf ./node_modules
npm install

Make sure you're using the correct Node version. If you use nvm, just run nvm use from the project root and the right version will be used automatically.

Tips for Learning from This Repo

Here are some tips to help you learn more effectively from this repo:

  1. Start with simple data structures — Understand Linked Lists and Queues before jumping into Tries or Graphs.
  2. Read the tests first — Before reading the implementation, read the tests. Tests explain "what" the code should do.
  3. Try implementing it yourself — Before looking at the solution, try writing the code yourself. If you get stuck, then look.
  4. Pay attention to complexity — Every time you read an algorithm, ask: "What's the best case, average case, and worst case?"
  5. Use the playground — Experimenting with code directly helps you understand concepts on a deeper level.
  6. Read the README per algorithm — Each algorithm has a README with visual explanations and additional links.
  7. Follow the order — Some algorithms have prerequisites. For example, understand Binary Search Trees before moving to Red-Black Trees.

Many problems in this repo frequently appear in coding interviews. Here are some of the most common:

  • Two Sum / Combination Sum — Finding number combinations that sum to a target. Often the first question in an interview.

  • Valid Parentheses — Checking whether parentheses are balanced. Can be solved with a simple stack.

  • Merge Two Sorted Lists — Merging two sorted linked lists. Tests understanding of linked lists.

  • Binary Search — Although it sounds simple, many people fail on the edge conditions. Practice makes perfect!

  • BFS/DFS on Graph — Graph traversal with different approaches. Critical for network or grid problems.

  • N-Queens Problem — Placing N queens on a chessboard without them attacking each other. A classic backtracking example.

  • Knapsack Problem — Optimizing item selection with weight constraints. Frequently appears in Google and Amazon interviews.

  • LRU Cache — Implementing an efficient cache. Combines a hash map with a doubly linked list.

All these problems have complete solutions in the repo. Just read, understand, and practice on your own.

Additional Complexity Concepts

Here's a comparison table of operation complexities for the data structures in this repo:

Data StructureAccessSearchInsertDeleteNotes
ArrayO(1)O(n)O(n)O(n)Index-based access
StackO(n)O(n)O(1)O(1)Push/pop from top
QueueO(n)O(n)O(1)O(1)Enqueue/dequeue
Linked ListO(n)O(n)O(1)O(n)Insert at head O(1)
Hash TableO(n)O(n)O(n)Perfect hash: O(1)
Binary Search TreeO(n)O(n)O(n)O(n)Balanced: O(log n)
B-TreeO(log n)O(log n)O(log n)O(log n)Efficient for disk I/O
Red-Black TreeO(log n)O(log n)O(log n)O(log n)Self-balancing
AVL TreeO(log n)O(log n)O(log n)O(log n)Stricter balance
Bloom FilterO(1)O(1)False positives possible

This table helps you choose the right data structure based on your needs. For example, if you need fast key-based access, the Hash Table is your answer. If you need sorted data with fast inserts, a Red-Black Tree or AVL Tree is more suitable.

References & Additional Learning Resources

This repo also provides links to other learning resources:

  • Data Structures and Algorithms on YouTube — Visual videos for deeper understanding of the concepts explained. Great for visual learners.

  • Data Structure Sketches — Visual sketches of data structures that help you understand concepts intuitively. Very useful when you need to remember the shape and structure of each data structure.

Complexity Cheat Sheet

As a quick reference, here's a Big O notation comparison:

NotationType10 elements100 elements1000 elements
O(1)Constant111
O(log N)Logarithmic369
O(N)Linear101001000
O(N log N)306009000
O(N²)Quadratic10010,0001,000,000
O(2^N)Exponential1,0241.26e+291.07e+301
O(N!)Factorial3,628,8009.3e+157

Notice how the differences become drastic as data size increases. An O(N!) algorithm that needs 3 million operations for 10 items requires an absurd number for 100 items. That's why choosing the right algorithm is so important.

Compatibility and Code Quality

This repo runs on Node.js >= 22 (last upgraded 6 months ago). The code is linted with ESLint and tested with Jest. Test coverage is quite comprehensive, and the repo also uses Husky for git hooks to maintain code quality.

With 220+ contributors and 1,153 commits, this repo is very actively maintained. The last commit was 3 weeks ago — showing the maintainer is still diligently updating and maintaining quality.

Who Should Use This Repo?

  • Developers preparing for interviews — Learn algorithms and data structures commonly asked in tech interviews. Each topic can be practiced directly with code.

  • Fresh graduates — Strengthening CS understanding that may have been lacking in university.

  • Self-taught developers — Filling knowledge gaps in computer science fundamentals. You don't need a CS degree to understand algorithms if you're willing to learn on your own.

  • Anyone who's curious — Wanting to understand the "why" behind how the technology we use every day works.

Conclusion

javascript-algorithms is an essential resource for every JavaScript developer. Whether you're preparing for an interview, want to improve your algorithmic skills, or simply want to understand how JavaScript works at a deeper level — this repo has everything.

The best thing about this repo: every algorithm is implemented from scratch without relying on external libraries. So you truly learn how things work, not just how to use built-in functions.

Plus, this repo has translated versions in many languages — including English — so you can read the explanations in your native language.

With 196K+ stars and counting, it's safe to say thousands of developers around the world have learned from this repo. Now it's your turn.

Go ahead, clone it, and start exploring. Happy coding!


Repository Information:

Namejavascript-algorithms
Author@trekhleb
Stars196K+
Forks31K+
Contributors220+
Commits1,153+
LicenseMIT
LanguageJavaScript (100%)
URLhttps://github.com/trekhleb/javascript-algorithms

More posts