DSA Notes
HubAlgorithm vs Data Structure — Key Differences, Definitions, and How They Work TogetherApplications of DSA — How Data Structures and Algorithms Power Real-World SoftwareTime and Space Complexity — A Complete BeginnerWhat is DSA? — A Complete BeginnerWhy Learn DSA? — Career Benefits, Real-World Impact, and Long-Term ValueAsymptotic Analysis — Complete Framework with Recurrence Relations and Master TheoremBest, Average, and Worst Case Analysis — A Practical Guide for Every AlgorithmBig O Notation — Complete Guide with Formal Definition, Rules, and ExamplesBig Omega Notation — Lower Bounds, Best Case, and Formal DefinitionBig Theta (Θ) Notation — Tight Bounds and Exact Growth RatesSpace Complexity — Memory Analysis, Auxiliary Space, and Time-Space TradeoffsTime Complexity Examples — 25 Worked Problems from Basic to AdvancedArray Interview Problems — 15 Classic Problems with Complete SolutionsArray Operations — Every Operation Explained with Code, Complexity, and Edge CasesArray Rotation — Algorithms, Techniques, and Interview ProblemsArray Searching — Linear Search, Binary Search, and Advanced TechniquesArrays — The Complete Introduction to the Most Fundamental Data StructureDynamic Arrays — How Python Lists and ArrayLists Work InternallyMultidimensional Arrays — 2D Arrays, Matrices, and Memory LayoutSliding Window Technique — Complete Guide with 10 Classic ProblemsAnagram Problems — Detection, Grouping, and Sliding Window VariationsPalindrome Problems — Check, Longest, Count, and Expand Around CenterPattern Searching — KMP, Rabin-Karp, and Boyer-Moore AlgorithmsString Interview Problems — 10 Classic Problems with Complete SolutionsString Matching — Longest Common Subsequence, Edit Distance, and Z-AlgorithmString Operations — Complete Reference with Complexity and ImplementationStrings — Complete Introduction to String Data Structure and OperationsCircular Linked List — Structure, Operations, and ApplicationsDoubly Linked List — Complete Implementation with Bidirectional OperationsLinked List Interview Problems — 12 Classic Problems with Complete SolutionsLinked Lists — A Complete Introduction with Memory Model and TypesLinked List Operations — Every Technique with Code and ComplexityReverse Linked List — All Approaches from Basic to AdvancedSingly Linked List — Complete Implementation with All OperationsBalanced Parentheses — Stack-Based Validation with All VariantsInfix, Prefix, and Postfix Expressions — Stack-Based Conversion and EvaluationStack Implementation — Three Complete Implementations with Edge CasesStack Interview Problems — 10 Classic Problems with Complete SolutionsStack — Complete Introduction to LIFO Data StructureStack Using Arrays — Memory Layout, Capacity Management, and PerformanceStack Using Linked List — Implementation, Analysis, and When to Use ItCircular Queue — The Ring Buffer Explained with ImplementationDeque — Double-Ended Queue with Complete Implementation and ApplicationsPriority Queue — Complete Guide from Concept to ImplementationQueue Applications — BFS, Level-Order Traversal, 01-BFS, and MoreQueue Implementation — Array, Linked List, and Two-Stack ApproachesQueue Interview Problems — 10 Classic Problems with Complete SolutionsQueue — Complete Introduction to the FIFO Data StructureAVL Tree - Self-Balancing Binary Search TreeBinary Search Tree (BST)Binary Tree - Structure and OperationsFenwick Tree (Binary Indexed Tree)Red-Black Tree - Another Balanced BSTSegment Tree - Range Query Data StructureTree Interview Problems CollectionTree Data Structure FundamentalsTree Traversals - Inorder, Preorder, Postorder, Level OrderHeap — Complete Introduction to the Priority-Based Tree Data StructureHeap Operations — Complete Reference with Complexity AnalysisHeap Problems — 8 Classic Interview Problems with Complete SolutionsMax Heap — Complete Implementation and ApplicationsMin Heap — Complete Implementation with All OperationsPriority Queue Using Heap — Implementation, Applications, and PatternsBellman-Ford Algorithm — Shortest Path with Negative Weights and Cycle DetectionBFS Algorithm — Breadth-First Search with All Applications and VariantsDFS Algorithm — Depth-First Search with Cycle Detection and All ApplicationsDijkstraFloyd-Warshall Algorithm — All-Pairs Shortest Paths with Complete AnalysisGraph Interview Problems — 12 Classic Problems with Complete SolutionsGraph — Complete Introduction to the Most Powerful Data StructureGraph Representation — Adjacency List, Matrix, Edge List with Complete AnalysisKruskalMinimum Spanning Tree — Definition, Properties, and ApplicationsPrimShortest Path Algorithms — Complete Comparison and Selection GuideTopological Sorting — DFS and BFS (KahnUnion-Find (DSU) in Graphs — Connected Components and Dynamic ConnectivitySeparate Chaining — Complete Implementation and AnalysisCollision Handling — Chaining vs Open Addressing Complete ComparisonHash Functions — Design, Properties, and Common ImplementationsHashing — Complete Introduction to Hash Tables and Hash FunctionsHashing Problems — 10 Classic Interview Problems with Complete SolutionsOpen Addressing — Linear Probing, Quadratic Probing, and Double HashingBubble Sort — Complete Analysis with Optimizations and When to Use ItCounting Sort — O(n+k) Sorting That Breaks the Comparison Lower BoundHeap Sort — Guaranteed O(n log n) with O(1) SpaceInsertion Sort — The O(n) Best Case Sort That Powers PythonMerge Sort — Complete Guide to the Guaranteed O(n log n) Stable SortQuick Sort — The Fastest Practical Sorting Algorithm with Complete AnalysisRadix Sort — O(nk) Digit-by-Digit Sorting for Large Integer RangesSelection Sort — Complete Analysis with Swaps Minimization PropertySorting Algorithm Comparison — The Complete Decision GuideSorting — Complete Introduction to Sorting AlgorithmsBinary Search — Complete Guide with All Variants and Proof of CorrectnessInterpolation Search — O(log log n) Search for Uniformly Distributed DataLinear Search — Complete Guide with All Variants and ApplicationsSearch Algorithm Comparison — Choosing the Right Search for Every SituationSearching Interview Problems — 10 Classic Problems with Complete SolutionsTernary Search — Finding Maximum/Minimum of Unimodal FunctionsBacktracking Introduction — The Recursive Exploration with UndoRecursion Basics — The Complete BeginnerRecursion Problems — 12 Classic Problems from Basic to AdvancedRecursion Tree — Visualizing Recursion for Complexity AnalysisRecursion vs Iteration — When to Use Each and How to ConvertTail Recursion — Definition, Optimization, and Converting to IterationDP Interview Problems — 12 Classic Problems with Pattern Recognition GuideDynamic Programming — Complete Introduction with Properties and Problem IdentificationFibonacci DP — From Exponential to Linear with Memoization and Matrix ExponentiationKnapsack Problem — 0/1, Unbounded, and Fractional with Complete AnalysisLongest Common Subsequence — Complete Guide with DP Table and String VariantsLongest Increasing Subsequence — O(n log n) with Patience SortingMatrix Chain Multiplication — Interval DP with Complete AnalysisMemoization — Top-Down Dynamic Programming with CachingTabulation — Bottom-Up Dynamic Programming with Complete Table BuildingActivity Selection Problem — Greedy Scheduling with Proof of CorrectnessFractional Knapsack — Greedy by Value Density with ProofGreedy Interview Problems — 10 Classic Problems with Complete SolutionsGreedy Algorithms — Complete Introduction with Proof TechniquesHuffman Coding — Optimal Prefix-Free Data CompressionJob Sequencing Problem — Greedy Scheduling with DeadlinesBacktracking — The Complete Guide to Recursive Exploration with UndoBacktracking Problems — 12 Classic Interview Problems with Complete SolutionsN-Queens Problem — Complete Solution with Backtracking and OptimizationRat in a Maze — Backtracking Path Finding with All SolutionsSubset Generation — All Subsets, Combinations, and Partitions with BacktrackingSudoku Solver — Backtracking with Constraint PropagationCodeforces Guide — Complete Strategy to Reach 1800+ RatingCommon CP Techniques — Essential Algorithms Every Competitive Programmer Must KnowContest Strategies — How to Perform Your Best in Competitive Programming ContestsCompetitive Programming — Complete Introduction for BeginnersFast Input/Output — Why I/O Speed Matters and Complete Templates for C++ and PythonLeetCode Guide — Complete Strategy to Crack FAANG InterviewsBit Manipulation — Complete Guide with All Tricks and Interview ProblemsBloom Filter — Space-Efficient Probabilistic Membership TestingComputational Geometry — Points, Lines, Convex Hull, and Geometric AlgorithmsDisjoint Set Union (DSU) — Union-Find with Path Compression and Union by RankRandomized Algorithms — Las Vegas, Monte Carlo, and Probabilistic TechniquesSkip List — The Probabilistic Data Structure that Competes with Balanced BSTsSuffix Array — Construction, LCP Array, and String Search ApplicationsTrie Data Structure — Complete Guide with Implementation and ApplicationsAutocomplete System Using TrieLibrary Management System Using DSARoute Finder Using GraphsMini Search Engine ProjectSocial Network Analysis Using GraphsEssential Coding Patterns for InterviewsDSA Cheatsheet: Quick ReferenceEssential DSA Interview QuestionsFAANG DSA Sheet: Company-Specific Patterns and ProblemsProblem Solving Strategies for Coding InterviewsComplexity CheatsheetImportant Algorithms SummaryBest Practice Platforms for DSARecommended Books for DSA
Solve 12 classic graph interview problems — number of islands, clone graph, Pacific Atlantic water flow, number of provinces, word ladder, rotting oranges, critical connections, reconstruct itinerary, swim in rising water, alien dictionary, minimum height trees, and evaluate division.
Problem 1 — Number of Islands
Example
def num_islands(grid):
"""Count connected components of '1's. DFS flood fill."""
if not grid: return 0
m, n = len(grid), len(grid[0])
count = 0
def dfs(r, c):
if r<0 or r>=m or c<0 or c>=n or grid[r][c]!='1': return
grid[r][c] = '#' # Mark visited
dfs(r+1,c); dfs(r-1,c); dfs(r,c+1); dfs(r,c-1)
for r in range(m):
for c in range(n):
if grid[r][c] == '1':
dfs(r, c); count += 1
return count
grid = [["1","1","0","0"],["1","1","0","0"],["0","0","1","0"],["0","0","0","1"]]
print(num_islands(grid)) # 3
Problem 3 — Pacific Atlantic Water Flow
Example
def pacific_atlantic(heights):
"""
Find cells that can flow to BOTH Pacific and Atlantic oceans.
BFS from ocean borders inward.
"""
m, n = len(heights), len(heights[0])
from collections import deque
def bfs(starts):
visited = set(starts)
queue = deque(starts)
while queue:
r, c = queue.popleft()
for dr, dc in [(0,1),(0,-1),(1,0),(-1,0)]:
nr, nc = r+dr, c+dc
if (0<=nr<m and 0<=nc<n and (nr,nc) not in visited
and heights[nr][nc] >= heights[r][c]):
visited.add((nr,nc)); queue.append((nr,nc))
return visited
pacific = [(0,c) for c in range(n)] + [(r,0) for r in range(1,m)]
atlantic = [(m-1,c) for c in range(n)] + [(r,n-1) for r in range(m-1)]
return list(bfs(pacific) & bfs(atlantic)) # Intersection
heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
print(len(pacific_atlantic(heights))) # Some cells reaching both oceans
Problem 4 — Number of Provinces (Connected Components)
Example
def find_circle_num(is_connected):
"""Count friend circles (connected components) in adjacency matrix."""
n = len(is_connected)
visited = set()
count = 0
def dfs(i):
for j in range(n):
if is_connected[i][j] == 1 and j not in visited:
visited.add(j); dfs(j)
for i in range(n):
if i not in visited:
visited.add(i); dfs(i); count += 1
return count
print(find_circle_num([[1,1,0],[1,1,0],[0,0,1]])) # 2
print(find_circle_num([[1,0,0],[0,1,0],[0,0,1]])) # 3
Problem 5 — Word Ladder (Shortest Transform)
Example
from collections import deque
def word_ladder(beginWord, endWord, wordList):
"""Shortest transformation sequence — BFS on implicit graph."""
word_set = set(wordList)
if endWord not in word_set: return 0
queue = deque([(beginWord, 1)])
visited = {beginWord}
while queue:
word, length = queue.popleft()
for i in range(len(word)):
for c in 'abcdefghijklmnopqrstuvwxyz':
new_word = word[:i] + c + word[i+1:]
if new_word == endWord: return length + 1
if new_word in word_set and new_word not in visited:
visited.add(new_word); queue.append((new_word, length+1))
return 0
print(word_ladder("hit","cog",["hot","dot","dog","lot","log","cog"])) # 5
Problem 6 — Rotting Oranges (Multi-Source BFS)
Example
def oranges_rotting(grid):
"""Multi-source BFS from all rotten oranges."""
from collections import deque
m, n = len(grid), len(grid[0])
queue = deque()
fresh = 0
for r in range(m):
for c in range(n):
if grid[r][c] == 2: queue.append((r,c,0))
elif grid[r][c] == 1: fresh += 1
if fresh == 0: return 0
max_time = 0
while queue:
r, c, time = queue.popleft()
for dr, dc in [(0,1),(0,-1),(1,0),(-1,0)]:
nr, nc = r+dr, c+dc
if 0<=nr<m and 0<=nc<n and grid[nr][nc]==1:
grid[nr][nc] = 2; fresh -= 1
max_time = max(max_time, time+1)
queue.append((nr,nc,time+1))
return max_time if fresh == 0 else -1
print(oranges_rotting([[2,1,1],[1,1,0],[0,1,1]])) # 4
print(oranges_rotting([[2,1,1],[0,1,1],[1,0,1]])) # -1
Problem 7 — Critical Connections (Bridges)
Example
def critical_connections(n, connections):
"""Find all bridges using Tarjan's algorithm."""
graph = [[] for _ in range(n)]
for u, v in connections:
graph[u].append(v); graph[v].append(u)
disc = [-1] * n; low = [-1] * n
timer = [0]; bridges = []
def dfs(u, parent):
disc[u] = low[u] = timer[0]; timer[0] += 1
for v in graph[u]:
if disc[v] == -1:
dfs(v, u)
low[u] = min(low[u], low[v])
if low[v] > disc[u]: # Bridge condition
bridges.append([u, v])
elif v != parent:
low[u] = min(low[u], disc[v])
dfs(0, -1)
return bridges
print(critical_connections(4, [[0,1],[1,2],[2,0],[1,3]])) # [[1,3]]
Problem 8 — Reconstruct Itinerary
Example
def find_itinerary(tickets):
"""
Reconstruct itinerary using Hierholzer's algorithm (Eulerian path).
"""
from collections import defaultdict
graph = defaultdict(list)
for src, dst in sorted(tickets, reverse=True):
graph[src].append(dst)
result = []
def dfs(airport):
while graph[airport]:
dfs(graph[airport].pop())
result.append(airport)
dfs("JFK")
return result[::-1]
print(find_itinerary([["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]]))
# ["JFK","MUC","LHR","SFO","SJC"]
Problem 9 — Minimum Height Trees
Example
def find_min_height_trees(n, edges):
"""
Find root(s) that minimize tree height.
Prune leaf nodes iteratively — roots are always the center.
Time: O(V)
"""
if n == 1: return [0]
from collections import deque, defaultdict
adj = defaultdict(set)
for u, v in edges:
adj[u].add(v); adj[v].add(u)
leaves = deque(i for i in range(n) if len(adj[i]) == 1)
remaining = n
while remaining > 2:
remaining -= len(leaves)
new_leaves = deque()
while leaves:
leaf = leaves.popleft()
neighbor = adj[leaf].pop()
adj[neighbor].remove(leaf)
if len(adj[neighbor]) == 1:
new_leaves.append(neighbor)
leaves = new_leaves
return list(leaves)
print(find_min_height_trees(4, [[1,0],[1,2],[1,3]])) # [1]
print(find_min_height_trees(6, [[3,0],[3,1],[3,2],[3,4],[5,4]])) # [3,4]
Problem 10 — Alien Dictionary (Topological Sort)
Example
def alien_order(words):
"""Determine character order from sorted alien dictionary."""
from collections import defaultdict, deque
order = defaultdict(set)
in_degree = {c: 0 for word in words for c in word}
for i in range(len(words)-1):
w1, w2 = words[i], words[i+1]
for c1, c2 in zip(w1, w2):
if c1 != c2:
if c2 not in order[c1]:
order[c1].add(c2); in_degree[c2] += 1
break
else:
if len(w1) > len(w2): return "" # Invalid
queue = deque(c for c in in_degree if in_degree[c] == 0)
result = []
while queue:
c = queue.popleft(); result.append(c)
for nc in order[c]:
in_degree[nc] -= 1
if in_degree[nc] == 0: queue.append(nc)
return "".join(result) if len(result) == len(in_degree) else ""
print(alien_order(["wrt","wrf","er","ett","rftt"])) # "wertf"
Problem 11 — Evaluate Division
Example
def calc_equation(equations, values, queries):
"""
Build weighted graph, use DFS to find path products.
"""
from collections import defaultdict
graph = defaultdict(dict)
for (a, b), val in zip(equations, values):
graph[a][b] = val; graph[b][a] = 1/val
def dfs(src, dst, visited):
if src not in graph or dst not in graph: return -1
if src == dst: return 1
visited.add(src)
for neighbor, weight in graph[src].items():
if neighbor not in visited:
result = dfs(neighbor, dst, visited)
if result != -1: return weight * result
return -1
return [dfs(a, b, set()) for a, b in queries]
print(calc_equation([["a","b"],["b","c"]],[2.0,3.0],[["a","c"],["b","a"]]))
# [6.0, 0.5]
Problem 12 — Swim in Rising Water
Example
def swim_in_water(grid):
"""
Minimum time to swim from (0,0) to (n-1,n-1).
Dijkstra: cost to reach cell = max(elevation along path).
"""
import heapq
n = len(grid)
dist = [[float('inf')]*n for _ in range(n)]
dist[0][0] = grid[0][0]
pq = [(grid[0][0], 0, 0)]
while pq:
d, r, c = heapq.heappop(pq)
if r==n-1 and c==n-1: return d
for dr,dc in [(0,1),(0,-1),(1,0),(-1,0)]:
nr,nc=r+dr,c+dc
if 0<=nr<n and 0<=nc<n:
new_d = max(d, grid[nr][nc])
if new_d < dist[nr][nc]:
dist[nr][nc] = new_d
heapq.heappush(pq,(new_d,nr,nc))
return dist[n-1][n-1]
print(swim_in_water([[0,2],[1,3]])) # 3
Pattern Summary
| Problem | Pattern | Algorithm |
|---|---|---|
| Number of Islands | Connected components | DFS/BFS flood fill |
| Clone Graph | Graph traversal + copy | BFS with hashmap |
| Pacific Atlantic | Multi-source reachability | BFS from both oceans |
| Word Ladder | Shortest path implicit graph | BFS |
| Rotting Oranges | Multi-source BFS | BFS with timestamps |
| Critical Connections | Bridge finding | Tarjan's DFS |
| Reconstruct Itinerary | Eulerian path | Hierholzer's |
| Min Height Trees | Tree center | Leaf pruning |
| Alien Dictionary | Topological sort | Kahn's BFS |
| Evaluate Division | Path product | DFS with weights |
| Swim in Water | Min bottleneck path | Dijkstra (max instead of sum) |
*Graphs section complete.*
Continue the lesson path
Study next in this module
01GraphsFloyd-Warshall Algorithm — All-Pairs Shortest Paths with Complete AnalysisMaster Floyd-Warshall algorithm completely — the all-pairs shortest path approach, the DP recurrence, step-by-step table filling, path reconstruction, negative cycle detection, transitive closure, and comparison with running Dijkstra V times.02GraphsGraph — Complete Introduction to the Most Powerful Data StructureA thorough introduction to graphs — what a graph is, formal definitions, all types of graphs (directed, undirected, weighted, cyclic, DAG), real-world applications, graph terminology (vertex, edge, degree, path, cycle, connectivity), and the two fundamental representations (adjacency list and matrix).03GraphsDijkstraMaster Dijkstra04GraphsGraph Representation — Adjacency List, Matrix, Edge List with Complete AnalysisMaster all graph representation methods — adjacency list with dictionary and array, adjacency matrix for dense graphs, edge list for algorithms like Kruskal