Skip to content

About

Algorithms to build your foundation as a Software Engineer

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

ย 

History

448 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš€ Algorithms & Data Structures Repository

A comprehensive collection of fundamental algorithms, data structures, and design patterns implemented in Python and TypeScript. Perfect for learning, interviews, and reference.

Python TypeScript License


๐Ÿ“š Table of Contents


๐Ÿ”„ Sorting Algorithms

Sorting algorithms arrange elements in a specific order. Here's a visual comparison:

Input: [64, 34, 25, 12, 22, 11, 90]

Bubble Sort:    [64,34,25,12,22,11,90] โ†’ Compare & swap adjacent elements
                [34,64,25,12,22,11,90] โ†’ Repeat until sorted
                ...
                [11,12,22,25,34,64,90] โœ“

Quick Sort:     [64,34,25,12,22,11,90]
                โ†“ Pick pivot (64)
                [34,25,12,22,11] | 64 | [90]
                โ†“ Recursively sort
                [11,12,22,25,34] | 64 | [90] โœ“

Complexity Comparison

Algorithm Best Average Worst Space Stable File
Bubble Sort O(n) O(nยฒ) O(nยฒ) O(1) โœ… bubble_sort.py
Selection Sort O(nยฒ) O(nยฒ) O(nยฒ) O(1) โŒ selection_sort.py
Insertion Sort O(n) O(nยฒ) O(nยฒ) O(1) โœ… insertion_sort.py
Merge Sort O(n log n) O(n log n) O(n log n) O(n) โœ… merge_sort.py
Quick Sort O(n log n) O(n log n) O(nยฒ) O(log n) โŒ quick_sort.py
Heap Sort O(n log n) O(n log n) O(n log n) O(1) โŒ heap_sort.py
Counting Sort O(n+k) O(n+k) O(n+k) O(k) โœ… counting_sort.py
Radix Sort O(d(n+k)) O(d(n+k)) O(d(n+k)) O(n+k) โœ… radix_sort.py
Bucket Sort O(n+k) O(n+k) O(nยฒ) O(n+k) โœ… bucket_sort.py
Shell Sort O(n log n) O(n^1.5) O(nยฒ) O(1) โŒ shell_sort.py
Comb Sort O(n log n) O(nยฒ/2^p) O(nยฒ) O(1) โŒ comb_sort.py
Intro Sort O(n log n) O(n log n) O(n log n) O(log n) โŒ intro_sort.py

Visual: Merge Sort Process

                    [64, 34, 25, 12, 22, 11, 90]
                           /              \
                  [64, 34, 25, 12]    [22, 11, 90]
                     /        \          /      \
              [64, 34]  [25, 12]   [22, 11]  [90]
               /   \     /   \      /   \      |
            [64]  [34] [25] [12] [22] [11]   [90]
               \   /     \   /      \   /      |
              [34, 64] [12, 25]  [11, 22]    [90]
                 \      /          \      /
              [12, 25, 34, 64]  [11, 22, 90]
                     \              /
              [11, 12, 22, 25, 34, 64, 90] โœ“

๐Ÿ” Searching Algorithms

Linear vs Binary Search

Linear Search:  [1, 3, 5, 7, 9, 11, 13]  Find: 7
                โ†‘  โ†‘  โ†‘  โ†‘  โœ“ Found at index 3
                O(n) - checks each element

Binary Search:  [1, 3, 5, 7, 9, 11, 13]  Find: 7
                โ†‘      โ†‘      โ†‘
                low   mid    high
                [1,3,5,7] โ† 7 is here
                [5,7] โ† 7 is here
                [7] โœ“ Found!
                O(log n) - halves search space
Algorithm Best Average Worst Space File
Linear Search O(1) O(n) O(n) O(1) linear_search.py
Binary Search O(1) O(log n) O(log n) O(1) binary_search.py
Breadth-First Search O(V+E) O(V+E) O(V+E) O(V) breadth_first_search.py
Depth-First Search O(V+E) O(V+E) O(V+E) O(V) depth_first_search.py
A* Search O(b^d) O(b^d) O(b^d) O(b^d) a_star.py
Iterative Deepening O(b^d) O(b^d) O(b^d) O(bd) iterative_deepening_search.py
Uniform Cost Search O((V+E)log V) O((V+E)log V) O((V+E)log V) O(V) uniform_cost_search.py

Graph Traversal Visualization

BFS (Level by level):        DFS (Deep first):
        A                            A
       / \                          / \
      B   C                        B   C
     / \   \                      /   / \
    D   E   F                    D   E   F

BFS Order: A โ†’ B โ†’ C โ†’ D โ†’ E โ†’ F
DFS Order: A โ†’ B โ†’ D โ†’ E โ†’ C โ†’ F

๐Ÿ•ธ๏ธ Graph Algorithms

Shortest Path Algorithms

Graph:        Dijkstra's (from A):      Bellman-Ford (from A):
   Aโ”€4โ”€B          A: 0                    A: 0
   โ”‚   โ”‚          B: 4                    B: 4
   2   5          C: 2                    C: 2
   โ”‚   โ”‚          D: 9                    D: 9
   Cโ”€1โ”€D          E: 12                   E: 12
    \ /
     10
      E
Algorithm Time Complexity Space Handles Negative Weights File
Dijkstra's O((V+E) log V) O(V) โŒ dijkstra.py
Bellman-Ford O(VE) O(V) โœ… bellman_ford.py
Floyd-Warshall O(Vยณ) O(Vยฒ) โœ… floyd_warshall.py
A* O(b^d) O(b^d) โŒ a_star.py

Minimum Spanning Tree

Original Graph:          Kruskal's MST:        Prim's MST:
   Aโ”€4โ”€B                    Aโ”€4โ”€B                Aโ”€4โ”€B
   โ”‚\ โ”‚\                   โ”‚   โ”‚                โ”‚   โ”‚
   2โ”‚ โ”‚โ”‚5                  2   โ”‚5               2   โ”‚5
   โ”‚ \โ”‚โ”‚                   โ”‚   โ”‚                โ”‚   โ”‚
   Cโ”€1โ”€D                   Cโ”€1โ”€D                Cโ”€1โ”€D
    \ /                      \ /                  \ /
     10                       10                   10
      E                        E                    E
Algorithm Time Complexity File
Kruskal's MST O(E log E) kruskal_mst.py
Prim's MST O(E log V) prim_mst.py

Other Graph Algorithms


๐Ÿ”ค String Algorithms

String Matching Visualization

Text:    "ABABDABACDABABCABCAB"
Pattern: "ABABCABAB"

KMP:     Uses failure function to skip characters
         ABABCABAB
         โ””โ”€โ”˜ (match prefix "AB")
         On mismatch, skip to next possible match

Rabin-Karp: Uses rolling hash
            Hash(pattern) = hash("ABABCABAB")
            Compare hash of each substring
            If hash matches, verify actual match
Algorithm Time Complexity Space File
KMP O(n + m) O(m) kmp_string_matching.py
Rabin-Karp O(n + m) avg, O(nm) worst O(1) rabin_karp.py

๐ŸŽฏ Optimization Algorithms

Simulated Annealing Process

Temperature: 1000ยฐ โ†’ 500ยฐ โ†’ 250ยฐ โ†’ 125ยฐ โ†’ ...
              โ†“       โ†“      โ†“      โ†“
Acceptance:  High โ†’ Medium โ†’ Low โ†’ Very Low
              โ†“       โ†“      โ†“      โ†“
Exploration: Wide โ†’ Narrow โ†’ Fine โ†’ Local
Algorithm Use Case File
Simulated Annealing Global optimization, TSP simulated_annealing.py
Hill Climbing Local optimization hill_climbing.py
Genetic Algorithm Evolutionary optimization GeneticAlgorithm.py

๐Ÿ“Š Data Structures

Visual Comparison

Array:        [1, 2, 3, 4, 5]
              O(1) access, O(n) insert/delete

Linked List:  1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5
              O(n) access, O(1) insert/delete

Stack:        [Top] 3
                โ†“   2
                โ†“   1
              LIFO (Last In, First Out)

Queue:        1 โ†’ 2 โ†’ 3 โ†’ [Front]
              FIFO (First In, First Out)

Binary Tree:       5
                  / \
                 3   7
                / \ / \
               2  4 6  8

Hash Table:   Key โ†’ Hash โ†’ Index โ†’ Value
              "apple" โ†’ hash โ†’ 3 โ†’ "red"
              O(1) average lookup

Complexity Table

Data Structure Access Search Insert Delete File
Array O(1) O(n) O(n) O(n) array.py
Linked List O(n) O(n) O(1) O(1) linked_list.py
Stack O(1) O(n) O(1) O(1) stack.py
Queue O(1) O(n) O(1) O(1) queue.py
Binary Tree O(n) O(n) O(n) O(n) binary_tree.py
BST O(log n) O(log n) O(log n) O(log n) binary_search_tree.py
Heap O(1) O(n) O(log n) O(log n) heap.py
Hash Table O(1) O(1) O(1) O(1) hash_table.py
Trie O(m) O(m) O(m) O(m) trie.py
Graph O(V+E) O(V+E) O(1) O(V+E) graph.py

๐ŸŽจ Design Patterns

Pattern Categories

Creational Patterns          Structural Patterns         Behavioral Patterns
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€          โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€         โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Singleton  โ”‚             โ”‚   Adapter   โ”‚            โ”‚  Observer   โ”‚
โ”‚  Factory    โ”‚             โ”‚  Decorator  โ”‚            โ”‚  Strategy   โ”‚
โ”‚  Builder    โ”‚             โ”‚   Facade    โ”‚            โ”‚  Command    โ”‚
โ”‚  Prototype  โ”‚             โ”‚   Proxy     โ”‚            โ”‚  Iterator   โ”‚
โ”‚Abstract Factโ”‚             โ”‚   Bridge    โ”‚            โ”‚   State     โ”‚
โ”‚             โ”‚             โ”‚  Composite  โ”‚            โ”‚  Visitor    โ”‚
โ”‚             โ”‚             โ”‚  Flyweight  โ”‚            โ”‚  Mediator   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚  Memento    โ”‚
                                                       โ”‚  Template   โ”‚
                                                       โ”‚  Chain of   โ”‚
                                                       โ”‚Responsibilityโ”‚
                                                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Quick Reference

Pattern Purpose File
Singleton Single instance singleton.py
Factory Object creation factory_method.py
Observer Event notification observer.py
Strategy Algorithm selection strategy.py
Decorator Add behavior dynamically decorator.py

See Design Patterns README for complete list.


๐Ÿ’ป CS Concepts (TypeScript)

Modern software development concepts with TypeScript examples:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  TypeScript Concepts                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  โœ“ Interfaces & Types                   โ”‚
โ”‚  โœ“ Generics & Constraints               โ”‚
โ”‚  โœ“ Async/Await & Promises               โ”‚
โ”‚  โœ“ Functional Programming               โ”‚
โ”‚  โœ“ Type Guards & Utilities              โ”‚
โ”‚  โœ“ Design Patterns in TS                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

See CS Concepts README for details.


๐Ÿ“ˆ Big O Notation

Understanding algorithm efficiency:

Complexity    Name          Example Operations
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
O(1)          Constant      Array access, hash lookup
O(log n)      Logarithmic   Binary search, tree operations
O(n)          Linear        Linear search, array iteration
O(n log n)    Linearithmic  Merge sort, heap sort
O(nยฒ)         Quadratic     Bubble sort, nested loops
O(2โฟ)         Exponential   Recursive Fibonacci
O(n!)         Factorial     Permutations

Visual Complexity Comparison

Operations
    โ”‚
    โ”‚  O(n!)
    โ”‚   โ•ฑ
    โ”‚  โ•ฑ
    โ”‚ โ•ฑ O(2โฟ)
    โ”‚โ•ฑ
    โ”œโ”€โ”€โ”€โ”€โ”€ O(nยฒ)
    โ”‚  โ•ฒ
    โ”‚   โ•ฒ O(n log n)
    โ”‚    โ•ฒ
    โ”‚     โ•ฒ O(n)
    โ”‚      โ•ฒ
    โ”‚       โ•ฒ O(log n)
    โ”‚        โ•ฒ
    โ”‚         โ•ฒ O(1)
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ Input Size

Big O Complexity Chart

Resources:


How they differ

All of these describe how runtime (or steps) grows as input size n grows. The key difference is the shape of that growth curve โ€” not the exact constant factors.

Think of n as โ€œhow much data you have.โ€ As n gets huge, only the dominant term matters.


O(1) โ€” constant

Growth: Does not grow with n. Same cost whether you have 10 items or 10 million.

Difference: The only class where doubling data does not increase work (for that single operation).

Example: Hash map get by key (average case) โ€” compute hash, jump to bucket, read value.

n = 1       โ†’ ~1 step
n = 1,000,000 โ†’ ~1 step

O(log n) โ€” logarithmic

Growth: Grows very slowly. Each step shrinks the problem (usually by half).

Difference from O(1): Still depends on n, but weakly โ€” adding one more step when you double n.

Example: Binary search in a sorted array.

n = 1,000     โ†’ ~10 comparisons
n = 1,000,000 โ†’ ~20 comparisons  (1000ร— more data, only ~2ร— work)

vs O(1): O(log n) is โ€œalmost constantโ€ for practical sizes, but technically still tied to n.


O(n) โ€” linear

Growth: Work grows in proportion to n. Double the data โ†’ roughly double the time.

Difference from O(log n): You typically touch every item once (or a fixed fraction of them), not repeatedly cut the problem in half.

Example: Find max in an unsorted array โ€” one pass.

n = 1,000     โ†’ ~1,000 steps
n = 1,000,000 โ†’ ~1,000,000 steps

Rule of thumb: One loop over n โ†’ often O(n).


O(n log n) โ€” linearithmic

Growth: Faster than linear, slower than quadratic. Common for efficient sorting and โ€œdivide, solve small pieces, combineโ€ algorithms.

Difference from O(n): You do O(n) work at each of O(log n) levels (typical divide-and-conquer pattern).

Example: Merge sort, heap sort.

n = 1,000     โ†’ ~10,000 operations (1000 ร— logโ‚‚ 1000 โ‰ˆ 10k)
n = 1,000,000 โ†’ ~20,000,000 (1M ร— 20)

vs O(nยฒ): For large n, n log n is much cheaper than nยฒ.

n n log n (rough) nยฒ
1,000 ~10k ~1M
10,000 ~130k ~100M

O(nยฒ) โ€” quadratic

Growth: If you double n, work roughly quadruples (4ร—).

Difference from O(n): Often nested loops โ€” for each of n items, you do something with all n again.

Example: Bubble sort, naive โ€œcompare every pair.โ€

for i in range(n):
    for j in range(n):
        ...
n = 1,000     โ†’ ~1,000,000 steps
n = 1,000,000 โ†’ ~1,000,000,000,000 steps  (impractical)

vs O(n log n): Sorting 1M items: merge sort ~20M ops vs naive O(nยฒ) ~1 trillion ops.


Side-by-side: what happens when n grows?

Complexity 10ร— more data (n โ†’ 10n) Feels like
O(1) Same Instant
O(log n) +~3 steps (base 2) Barely notice
O(n) ~10ร— slower Scales with data
O(n log n) ~10ร— + a bit more (log factor) Fine for big data
O(nยฒ) ~100ร— slower Dies on large n

Visual intuition (relative cost at large n)

cost
  โ†‘
  โ”‚                              โ•ฑ O(nยฒ)
  โ”‚                         โ•ฑ
  โ”‚                    โ•ฑ O(n log n)
  โ”‚               โ•ฑ
  โ”‚          โ•ฑ O(n)
  โ”‚     โ•ฑ
  โ”‚โ•ฑ O(log n)  (stays very flat)
  โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ O(1) (flat line)
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ n

How to tell them apart in code

Pattern Typical complexity
Single lookup, no loop over n O(1)
Halve/search tree each step O(log n)
One loop over n O(n)
Sort efficiently (merge/heap) O(n log n)
Two nested loops over n O(nยฒ)

Important: Big-O ignores constants. O(1000n) is still O(n). O(n) with a tiny n can beat O(log n) with huge overhead in practice โ€” but as n grows, the class wins.


One sentence each

  • O(1): Size doesnโ€™t matter for that operation.
  • O(log n): Repeatedly cut the problem in half.
  • O(n): Do something once per item.
  • O(n log n): Do โ€œper itemโ€ work across log-many layers (smart divide-and-conquer).
  • O(nยฒ): Every item interacts with every other item (nested loops).

If you want, we can walk through one concrete algorithm (e.g. linear search vs binary search vs bubble sort) step-by-step with n = 8 so the counts are explicit.

๐Ÿงฎ Other Algorithms

Mathematical & Utility Algorithms

Advanced Algorithms


๐Ÿ“– How to Use

Running Python Algorithms

# Run any algorithm file
python Algorithms/bubble_sort.py

# Or import in your code
from Algorithms.bubble_sort import bubble_sort

arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print(arr)  # [11, 12, 22, 25, 34, 64, 90]

Using TypeScript Concepts

# Install TypeScript
npm install -g typescript

# Compile TypeScript files
tsc CS\ Concepts/interfaces.ts

# Or use with a bundler

Using Data Structures

from Data_Structures.linked_list import LinkedList

ll = LinkedList()
ll.append(1)
ll.append(2)
ll.append(3)
print(ll)  # 1 -> 2 -> 3

๐ŸŽฏ Learning Path

Beginner

  1. Start with Linear Search and Bubble Sort
  2. Learn Arrays and Linked Lists
  3. Understand Stack and Queue

Intermediate

  1. Master Binary Search and Quick Sort
  2. Learn Trees and Hash Tables
  3. Study BFS and DFS

Advanced

  1. Implement Graph Algorithms (Dijkstra, MST)
  2. Master Dynamic Programming
  3. Study Design Patterns

๐Ÿ“š Additional Resources


๐Ÿค Contributing

Contributions are welcome! Please ensure:

  • Code follows existing style
  • Includes proper documentation
  • Has example usage
  • Time/space complexity noted

About

Algorithms to build your foundation as a Software Engineer

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages