Some problems are naturally two-dimensional: printing grids, building tables, scanning pairs \((i,j)\), summing over regions like \(1 \le j \le i \le N\). A nested loop is just a loop inside another loop—perfect for “for each row, for each column” patterns. The key mental model:
- The outer loop picks a row (runs slowly).
- For each row, the inner loop runs to completion (runs fast).
- After the inner loop finishes, control returns to the outer loop for the next row.
Once you see nested loops as row × column, the control flow becomes predictable.
Example 1 — A “visual” triangle of symbols
Goal: print a left-aligned triangle of * with height N.
*
**
***
****
#include <iostream>
int main() {
int N;
std::cout << "Triangle height N: ";
std::cin >> N;
for (int row = 1; row <= N; row = row + 1) {
// Print 'row' stars on this line
for (int k = 1; k <= row; k = k + 1) {
std::cout << '*';
}
std::cout << '\n'; // move to the next line
}
return 0;
}
How it runs:
row = 1: inner loop prints 1 star → newlinerow = 2: inner loop prints 2 stars → newline
… up torow = N.
Variant: right-aligned triangle (spaces + stars)
*
**
***
****
#include <iostream>
int main() {
int N;
std::cout << "Triangle height N: ";
std::cin >> N;
for (int row = 1; row <= N; row = row + 1) {
// First, N-row spaces
for (int s = 1; s <= N - row; s = s + 1) {
std::cout << ' ';
}
// Then, row stars
for (int k = 1; k <= row; k = k + 1) {
std::cout << '*';
}
std::cout << '\n';
}
return 0;
}
Two inner loops make the “shape” obvious: spaces, then stars.
Example 2 — Multiplication table (1…N) as a grid
We build an \(N\times N\) grid where the entry in row \(i\), column \(j\) is \(i \times j\).
#include <iostream>
int main() {
int N;
std::cout << "Table size N: ";
std::cin >> N;
// Optional header row
std::cout << " "; // small left margin
for (int j = 1; j <= N; j = j + 1) {
std::cout << j << '\t';
}
std::cout << '\n';
for (int i = 1; i <= N; i = i + 1) {
std::cout << i << " | "; // row label
for (int j = 1; j <= N; j = j + 1) {
std::cout << (i * j) << '\t';
}
std::cout << '\n';
}
return 0;
}
We use '\t' (a tab) for simple column separation—no extra libraries needed.
Example 3 — Double sums: full square vs. triangle
Sum over all pairs \((i,j)\) in a square \(1\le i,j\le N\)
#include <iostream>
int main() {
int N;
std::cout << "N for double sum: ";
std::cin >> N;
long long S = 0; // use a wider type for safety
for (int i = 1; i <= N; i = i + 1) {
for (int j = 1; j <= N; j = j + 1) {
S = S + (i * j);
}
}
std::cout << "Sum_{i=1..N} Sum_{j=1..N} (i*j) = " << S << '\n';
return 0;
}
Sum over a triangle \(1\le j\le i\le N\) (avoid double counting)
#include <iostream>
int main() {
int N;
std::cout << "N for triangular sum: ";
std::cin >> N;
long long T = 0;
for (int i = 1; i <= N; i = i + 1) {
for (int j = 1; j <= i; j = j + 1) { // note j <= i
T = T + (i + j);
}
}
std::cout << "Sum over 1<=j<=i<=N of (i+j) = " << T << '\n';
return 0;
}
By changing the inner loop’s check from j <= N to j <= i, we restrict to the lower triangle.
Example 4 — Counting lattice points in a disk
Count integer pairs \((x,y)\) with \(-R \le x,y \le R\) that satisfy \(x^2 + y^2 \le R^2\).
#include <iostream>
int main() {
int R;
std::cout << "Radius R: ";
std::cin >> R;
int count = 0;
for (int x = -R; x <= R; x = x + 1) {
for (int y = -R; y <= R; y = y + 1) {
if (x*x + y*y <= R*R) {
count = count + 1;
}
}
}
std::cout << "Lattice points with x^2 + y^2 <= R^2: " << count << '\n';
return 0;
}
Mathematically, this explores a 2D region using a rectangular scan and an if to test membership.
Reading the flow (what runs when?)
For the classic form
for (int i = 1; i <= A; i = i + 1) {
for (int j = 1; j <= B; j = j + 1) {
// body
}
}
the order is:
i = 1, thenjruns1..Bcompletelyi = 2, thenjruns1..Bcompletely
… up toi = A.
The inner loop resets each time the outer loop advances.
Common pitfalls (and fixes)
- Using the same variable name for both loops.
- Fix: use distinct names (
row/col,i/j).
- Fix: use distinct names (
- Forgetting the newline after finishing a row in “visual” problems.
- Fix: print
'\n'once per row, after the inner loop completes.
- Fix: print
- Off-by-one in triangular regions (
j < ivsj <= i).- Fix: write down a tiny case (e.g.,
N = 3) and list the pairs to confirm.
- Fix: write down a tiny case (e.g.,
- Performance surprises: nested loops over
Ngo like (N^2).- Fix: start with small
Nto test, then scale up.
- Fix: start with small
Key takeaways
- A nested loop is a natural way to model row × column or pairwise work.
- The inner loop runs to completion for each outer iteration.
- Shapes (rectangle vs. triangle) are controlled by the inner loop’s bounds and simple
iftests. - Visual tasks (patterns) and mathematical tasks (tables, sums, regions) both become straightforward when you think in terms of rows and columns.
