Expert · Competitive programming, interviews and careers · topic 39 of 42 · 40 min
Core DSA patterns in C++
Explanation
Why patterns?
Most problems are variations of a few ideas. When you can recognise the pattern ("sum of a range many times? prefix sums"), the C++ code is short because the STL does the heavy lifting. DSA means Data Structures and Algorithms.
1. Prefix sums: fast range sums
vector<long long> pre(n + 1, 0);
for (int i = 0; i < n; ++i) pre[i + 1] = pre[i] + a[i];
// sum of a[l..r] (inclusive, 0-based) = pre[r + 1] - pre[l], in O(1) per query2. Two pointers on sorted data
// Does a sorted array have two values adding up to target?
int i = 0, j = n - 1;
while (i < j) {
long long s = a[i] + a[j];
if (s == target) { /* found */ break; }
if (s < target) ++i; else --j;
}3. Binary search on the answer
If a yes/no question "can we do it with value X?" switches from no to yes at one point as X grows, you can binary search X. Example: the smallest daily speed that finishes reading all chapters in D days. Each check is O(n), and binary search needs about 30–60 checks, so the total is O(n log maxValue).
long long lo = 1, hi = 1'000'000'000;
while (lo < hi) {
long long mid = lo + (hi - lo) / 2; // avoids overflow of (lo + hi)
if (canFinish(mid)) hi = mid; else lo = mid + 1;
}
// lo is the smallest value for which canFinish is true4. Hashing: seen before?
unordered_map<long long, int> seenAt; // value -> index
for (int i = 0; i < n; ++i) {
if (auto it = seenAt.find(target - a[i]); it != seenAt.end()) {
cout << it->second << ' ' << i << '\n'; // the "two sum" problem in O(n)
break;
}
seenAt[a[i]] = i;
}5. Graphs: BFS and DFS
// Shortest path in an unweighted graph with BFS
vector<vector<int>> adj(n); // adjacency list
vector<int> dist(n, -1);
queue<int> q;
dist[src] = 0;
q.push(src);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
q.push(v);
}
}
}DFS (depth-first search) goes deep before backtracking, using recursion or a stack. It finds connected components, detects cycles and drives topological sort. For n up to about 10^5, an iterative DFS avoids stack overflow from deep recursion.
6. Dynamic programming (DP)
// Number of ways to climb n stairs taking 1 or 2 steps at a time
vector<long long> ways(n + 1, 0);
ways[0] = 1;
for (int i = 1; i <= n; ++i) {
ways[i] = ways[i - 1] + (i >= 2 ? ways[i - 2] : 0);
}Pattern finder
| Clue in the problem | Try |
|---|---|
| Many range-sum queries on a fixed array | prefix sums |
| Sorted array, pairs or windows | two pointers / sliding window |
| "Minimum X such that…" with a monotonic check | binary search on the answer |
| "Have we seen…", counting frequencies | unordered_map / set |
| Grid or network, fewest steps | BFS |
| Count ways / best value from choices that overlap | dynamic programming |
| Always pick the current best | greedy, often with sort or priority_queue |
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Core DSA patterns in C++ · 1/6
A few patterns solve most coding round problems. Learn to recognise them.
Prefer a video by a teacher? Find free videos on “dsa patterns prefix sum two pointers binary search on answer bfs c++” on YouTube ↗
In real life: Metro route planning
A city metro app answers "fewest stations from A to B". Stations are nodes and direct links are edges, so it is a breadth-first search on an unweighted graph. For "fastest by minutes", each edge gets a travel time and the app switches to Dijkstra's algorithm with a min priority_queue.
#include <bits/stdc++.h>
using namespace std;
int main() {
int n = 5; // stations 0..4
vector<vector<int>> adj(n);
auto link = [&](int a, int b) { adj[a].push_back(b); adj[b].push_back(a); };
link(0, 1); link(1, 2); link(2, 3); link(0, 4); link(4, 3);
vector<int> dist(n, -1);
queue<int> q;
dist[0] = 0; q.push(0);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) if (dist[v] == -1) { dist[v] = dist[u] + 1; q.push(v); }
}
cout << dist[3] << '\n'; // 2 (0 → 4 → 3)
}Practice (0/4 done)
Prefix sums (in Python, same idea as C++): write range_sums(nums, queries) where queries is a list of (l, r) pairs, 0-based and inclusive. Return a list with the sum of nums[l..r] for each query. Build a prefix array once so each query is O(1).
Two pointers: nums is sorted in increasing order. Write pair_with_sum(nums, target) that returns a tuple (i, j) with i < j and nums[i] + nums[j] == target, or None if there is no such pair. Use one pointer at each end (O(n)).
A grid maze asks for the minimum number of moves from start to exit. Which algorithm fits?
In C++ on your computer, solve these CSES problems: "Static Range Sum Queries" (prefix sums), "Sum of Two Values" (hashing or two pointers) and "Labyrinth" (BFS on a grid). Write the pattern used at the top of each file as a comment.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
- STL algorithms: sort, find, count, accumulate and binary searchThe Standard Template Library (STL)
- C++20 ranges, views and other C++20 essentialsModern C++: lambdas, C++17 and C++20 essentials
- Competitive programming with C++: setup and time limitsCompetitive programming, interviews and careers · the topic just before this one
Related topics
- Classic C++ pitfalls in contests and coding roundsCompetitive programming, interviews and careers · same module
- C++ interview questions and how to answer themCompetitive programming, interviews and careers · same module
- Data-structure questions in JavaScriptJavaScript Programming (language in depth) · Interview preparation and career
- Depth-first search (DFS)Data Structures and Algorithms (DSA) for interviews · Graphs
- Traversals: DFS and BFSData Structures and Algorithms (DSA) for interviews · Trees and binary search trees
- Prefix sums and difference arraysData Structures and Algorithms (DSA) for interviews · Arrays and strings
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
After building prefix sums once, how long does one range-sum query take?
Answer: O(1)
It is a single subtraction.
Why write mid = lo + (hi - lo) / 2 instead of (lo + hi) / 2?
Answer: It avoids overflow when lo + hi is larger than the type can hold
lo + hi can overflow for large values; the difference cannot.
What is the time complexity of BFS with an adjacency list?
Answer: O(V + E)
Each vertex and edge is processed a constant number of times.
What makes dynamic programming faster than plain recursion for problems like Fibonacci?
Answer: Each sub-problem's answer is stored and reused instead of recomputed
Overlapping sub-problems are solved once.
What is the time complexity of binary search?Related
Directed edges 0→1, 0→2, 1→3, 2→3. A DFS from 0 meets vertex 3 a second time. Is there a cycle?Related
Answer: No: 3 is finished (black), not on the current path
Only an edge to a grey vertex (on the current path) closes a cycle. This is a diamond.
Which answer about std::move is correct?Related
Answer: It is a cast to an rvalue; the actual move happens in the move constructor or assignment
std::move itself does no work at run time.
A perfect binary tree has n nodes. What is the worst extra space of BFS on it?Related
Answer: O(n), because the last level holds about n/2 nodes
The queue holds a whole level at a time, and the bottom level of a perfect tree has about half of all nodes.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Competitive programming, interviews and careers” before its exam: Classic C++ pitfalls in contests and coding rounds, C++ interview questions and how to answer them, Careers with C++ and your next steps.
- Module 10 exam: Contests, interviews and careers · 12 questions · 20 min, without help. 5 topics of this module still to finish first.
- 42 topics left in the course before the final exam.
← Previous: Competitive programming with C++: setup and time limits