Welcome to the Algorithmic Patterns repository! This project is a curated collection of common algorithmic patterns used to solve a wide range of coding problems efficiently. Each pattern includes a conceptual overview, brute-force implementations, optimized solutions, and practice questions.
- ๐ช Sliding Window
- ๐ Two Pointers
- ๐ข Fast & Slow Pointers
- โ๏ธ Merge Intervals
- ๐ Cyclic Sort
- ๐ Backtracking
- ๐ Binary Search
- ๐ง Dynamic Programming
- ๐ Greedy Algorithms
- ๐ธ๏ธ Graphs
The Sliding Window pattern is used to perform a required operation on a specific window size of a given array or linked list, such as finding the longest subarray containing all 1s.
graph LR
subgraph Array
A[1] --- B[2] --- C[3] --- D[4] --- E[5] --- F[6] --- G[7]
end
subgraph Window
B --- C --- D
end
style B fill:#f96,stroke:#333
style C fill:#f96,stroke:#333
style D fill:#f96,stroke:#333
In problems where we deal with sorted arrays (or linked lists) and need to find a set of elements that fulfill certain constraints, the Two Pointers approach is very effective.
graph LR
subgraph Array
L[Left Pointer] --> A[1]
A --- B[3] --- C[4] --- D[6] --- E[8] --- F[10]
R[Right Pointer] --> F
end
style A fill:#4CAF50,stroke:#333
style F fill:#F44336,stroke:#333
Also known as the Hare & Tortoise algorithm, this pattern uses two pointers which move through the array (or sequence/linked list) at different speeds.
graph LR
S[Slow 1x] --> Node1((1))
F[Fast 2x] --> Node1
Node1 --> Node2((2))
Node2 --> Node3((3))
Node3 --> Node4((4))
Node4 --> Node2
linkStyle 3 stroke:#f66,stroke-width:2px;
This pattern is used to deal with overlapping intervals. This is a common pattern for problems involving meetings, scheduling, or range merges.
graph LR
subgraph Internal State
I1[1-----4]
I2[ 2---5]
I3[ 6---8]
end
I1 --- I2 --> Merged[1-------5]
Merged --- I3 --> Result[1-------5, 6---8]
This pattern describes an interesting approach to deal with problems involving arrays containing numbers in a given range.
graph TD
A["[3, 1, 5, 4, 2]"] --> B["Swap 3 with 2 (index 2)"]
B --> C["[2, 1, 5, 4, 3]"]
C --> D["Swap 2 with 1 (index 1)"]
D --> E["[1, 2, 5, 4, 3]..."]
Backtracking is an algorithmic technique for solving problems recursively by trying to build a solution incrementally, one piece at a time, removing those solutions that fail to satisfy the constraints.
graph TD
Root((Root)) --> C1((Choice 1))
Root --> C2((Choice 2))
C1 --> C1a((Success))
C1 --> C1b((Fail))
C1b -.-> C1
style C1b fill:#f66
Binary search is an efficient algorithm for finding an item from a sorted list of items. It works by repeatedly dividing in half the portion of the list that could contain the item.
graph LR
A[1, 3, 5, 7, 9, 11, 13] --> Mid[7]
Mid --> Left[1, 3, 5]
Mid --> Right[9, 11, 13]
Dynamic Programming (DP) is an algorithmic technique for solving an optimization problem by breaking it down into simpler subproblems and utilizing the fact that the optimal solution to the overall problem depends upon the optimal solution to its subproblems.
graph TD
Fib5(Fib 5) --> Fib4(Fib 4)
Fib5 --> Fib3(Fib 3)
Fib4 --> Fib3
Fib4 --> Fib2(Fib 2)
style Fib3 fill:#4CAF50
A greedy algorithm is any algorithm that follows the problem-solving heuristic of making the locally optimal choice at each stage with the intent of finding a global optimum.
graph TD
Start((Start)) -->|Best Local| NodeA((Node A: 10))
Start --> NodeB((Node B: 5))
NodeA --> Goal((Goal))
Graph algorithms are used to solve problems that can be represented as nodes and edges. Common patterns include BFS, DFS, and shortest path algorithms.
graph LR
A((A)) --- B((B))
A --- C((C))
B --- D((D))
C --- D
D --- E((E))
Ankush Thakur
LinkedIn
Distributed under the MIT License.
