Part 1 · Lesson 6 · 20 min read

Nested Loops and Patterns

A loop inside a loop is a grid: rows outside, columns inside. Built up with star and number patterns until you can draw any shape.

On this page

  1. A loop inside a loop is a grid
  2. The clock picture
  3. Traced: every (row, column) pair
  4. Building one row, then printing it
  5. The three-question recipe for any pattern
  6. How many times does the inside run?
  7. Practice: 11 patterns and grids
  8. Make it stick

A loop inside a loop is a grid

A nested loop is a loop that has another loop inside its body. The outer loop is the first one. The inner loop is the one inside it. One rule makes nested loops easy to predict: for every single iteration of the outer loop, the inner loop runs completely, from start to finish.

Picture a grid. The outer loop picks a row. The inner loop walks along every column of that row. When the row is done, the outer loop moves down one row, and the inner loop starts again from the first column. This is why the outer variable is usually called i (row) and the inner one j (column).

Patterns (stars, numbers, triangles) are a common way to practise this. Companies often ask them in campus and first-round interviews, because they test whether you can control two loops at once. After this lesson, comparing every pair of items in an array (Lessons 8 and 21) will feel natural.

The clock picture

A clock works like a nested loop. The hour hand is the outer loop. The minute hand is the inner loop. For every one step of the hour hand, the minute hand goes all the way round (60 steps) and then starts again from 0.

Traced: every (row, column) pair

step 1 / 17
Check the condition
Outer: row i = 1

The outer loop starts row 1.

▶for (let i = 1; i <= 2; i++) {2  for (let j = 1; j <= 3; j++) {3    console.log(i, j);4  }5}
Variables
i1
Console
(nothing printed yet)
Watch j restart at 1 every time i changes. The inner loop finishes completely before i moves on. · interactive
Dry run · 2 rows × 3 columns
i (row)j values in this rowPrinted
11, 2, 31 1 · 1 2 · 1 3
21, 2, 32 1 · 2 2 · 2 3

Total prints: 2 × 3 = 6.

Building one row, then printing it

console.log always ends the line, so you cannot print stars one by one on the same line. Do this instead. Start each row with an empty string (a string with no characters, written as ""). Let the inner loop add characters to it. Print the row when it is complete.

JavaScript
const N = 3;for (let i = 1; i <= N; i++) {      // one iteration per ROW  let row = "";                     // a fresh, empty row each time  for (let j = 1; j <= N; j++) {    // one iteration per COLUMN    row += "*";                     // add one star to this row  }  console.log(row);                 // print the finished row — AFTER the inner loop}/* Output:**********/
Where each line goes is the whole skill
  • let row = "" goes inside the outer loop, before the inner one. Then every row starts empty.
  • console.log(row) goes inside the outer loop, after the inner one. Then it prints once for each row.
  • If you put the print inside the inner loop, you get one line for every star instead.

The three-question recipe for any pattern

  1. How many rows? That is the outer loop: i from 1 to N.
  2. In row i, what is printed, and how many of it? Write it down for rows 1, 2, 3 and 4. Then look for a rule that uses i, such as “i stars”, “N − i + 1 stars” or “the numbers 1 to i”.
  3. Build it: the inner loop (or loops) follows that rule. Then print the row.
Dry run · discovering the rule for a right triangle (N = 4)
Row iLooks likeStars in the row
1*1
2**2
3***3
4****4

Stars = i. So the inner loop is for (let j = 1; j <= i; j++). Its stopping point depends on the outer variable.

How many times does the inside run?

JavaScript
let count = 0;for (let i = 1; i <= 4; i++) {  for (let j = 1; j <= 4; j++) {    count++;  }}console.log(count); // 16  (4 rows × 4 columns)

A loop of N inside a loop of N runs its body N × N times. For N = 1,000 that is a million iterations. Keep this in mind. In Lesson 12 it is called O(n²) (“order n squared”), a way to say that the work grows with the square of the input size. A big part of DSA is learning tricks to avoid doing all N × N steps.

Practice: 11 patterns and grids

For each one, answer the three recipe questions on paper first. Most examples use N = 4.

Q1Solid squareEasy

Print an N × N square of stars.

Example 1
Input: N = 4
Output:
****
****
****
****
Explanation: 4 rows, and every row has 4 stars.
Stuck? Open one hint at a time
Hint 1
How many rows? How many stars in each row — does that number change from row to row?
Hint 2
Use the outer loop for the rows. The inner loop adds N stars to a row string. Then print the row.
Show all 2 solutions with explanations
Approach 1Nested loops
The idea

The outer loop makes N rows. For each row, the inner loop adds N stars, then the row is printed.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= N; j++) {    row += "*";  }  console.log(row);}/* Output:*****************/
How it works

The inner count (N) does not depend on i, so every row is the same. This is the template (the basic shape to copy) for every pattern below.

Approach 2Build the row once with repeat
The idea

Every row is identical, so make it once with "*".repeat(N) and print it N times.

JavaScript
const N = 4;const row = "*".repeat(N);for (let i = 1; i <= N; i++) {  console.log(row);}/* Output:*****************/
How it works

text.repeat(k) is a string method (a function that belongs to text) that returns the text repeated k times. Building the row once avoids doing the same work in every row.

Which approach should you use?

Write Approach 1 while you are learning. Interviewers who ask pattern questions want to see the two loops. Use repeat in everyday code.

Q2Right-angled triangleEasy

Row i has i stars.

Example 1
Input: N = 4
Output:
*
**
***
****
Explanation: Row 1 has 1 star, row 2 has 2 stars, and so on. Row 4 has 4 stars.
Stuck? Open one hint at a time
Hint 1
Write down the number of stars in rows 1, 2, 3, 4. How does it relate to the row number i?
Hint 2
Row i has i stars, so the inner loop runs while j <= i.
Show all 3 solutions with explanations
Approach 1Inner loop up to i
The idea

This is the same as the square, with one change: the inner loop stops at i instead of N.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= i; j++) {    row += "*";  }  console.log(row);}/* Output:***********/
How it works

The key to every triangle is this: the stopping point of the inner loop depends on the outer variable.

Approach 2One loop, a growing row
The idea

Each row is the previous row plus one star. Keep the row from one iteration to the next, and add one star each time.

JavaScript
const N = 4;let row = "";for (let i = 1; i <= N; i++) {  row += "*";          // one more star than last time  console.log(row);}/* Output:***********/
How it works

Here row is declared outside the loop, so it keeps its stars from the previous iteration. Only one loop is needed.

Approach 3repeat(i)
The idea

Row i is simply "*".repeat(i).

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  console.log("*".repeat(i));}/* Output:***********/
How it works

This is the shortest version. The inner loop is hidden inside repeat.

Which approach should you use?

Approach 1 is the one to understand. Approach 2 shows a useful idea. When each row extends the previous one, keep the previous row instead of building it again.

Q3Number triangleEasy

Row i shows the numbers 1 to i.

Example 1
Input: N = 4
Output:
1
1 2
1 2 3
1 2 3 4
Explanation: Row i shows the numbers from 1 to i, separated by spaces.
Stuck? Open one hint at a time
Hint 1
The shape is the same as question 2. What do you print instead of a star?
Hint 2
Print the column number j. Remove the extra space at the end with trimEnd().
Show all 2 solutions with explanations
Approach 1Print the column number j
The idea

Use the same loops as the triangle, but add j and a space instead of a star.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= i; j++) {    row += j + " ";  }  console.log(row.trimEnd());   // remove the space after the last number}/* Output:11 21 2 31 2 3 4*/
How it works

trimEnd() removes spaces at the end of the text. Some online judges (websites that check your answer automatically) compare output character by character. For them, a space at the end of a line can make a correct answer fail.

Approach 2One loop, a growing row
The idea

Each row is the previous row with the next number added.

JavaScript
const N = 4;let row = "";for (let i = 1; i <= N; i++) {  row += (i === 1 ? "" : " ") + i;   // add a space before every number except the first  console.log(row);}/* Output:11 21 2 31 2 3 4*/
How it works

Adding the space before each number (except the first) avoids a space at the end, so you do not need trimEnd.

Which approach should you use?

Both are correct. Approach 1 matches the general recipe, and it is easier to change for other patterns.

Q4Repeated row numberEasy

Row i shows the number i, i times.

Example 1
Input: N = 4
Output:
1
2 2
3 3 3
4 4 4 4
Explanation: Row i shows the number i, written i times.
Stuck? Open one hint at a time
Hint 1
Compare with question 3. Which variable do you print now: the row i or the column j?
Show all 2 solutions with explanations
Approach 1Print the row number i
The idea

This is question 3 with one letter changed. Print i instead of j.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= i; j++) {    row += i + " ";  }  console.log(row.trimEnd());}/* Output:12 23 3 34 4 4 4*/
How it works

Pattern questions train you to say whether a value depends on the row or on the column.

Approach 2repeat a small piece
The idea

Repeat the small piece of text "i " (the number i and a space) i times. Then remove the final space.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  console.log((i + " ").repeat(i).trimEnd());}/* Output:12 23 3 34 4 4 4*/
How it works

(i + " ") is text like "3 ". Repeating it 3 times gives "3 3 3 ".

Q5Inverted triangleEasy

Row 1 has N stars, and each row after it has one star fewer.

Example 1
Input: N = 4
Output:
****
***
**
*
Explanation: Row 1 has 4 stars and each row after it has one fewer.
Stuck? Open one hint at a time
Hint 1
Make a small table: row 1 has 4 stars, row 2 has 3, row 3 has 2 and row 4 has 1. What formula using N and i gives these numbers?
Hint 2
Stars in row i = N − i + 1. Or count i down from N to 1.
Show all 2 solutions with explanations
Approach 1Formula N − i + 1
The idea

Let the rows count up, and give row i exactly N − i + 1 stars.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= N - i + 1; j++) {    row += "*";  }  console.log(row);}/* Output:***********/
How it works
Dry run · stars per row, N = 4
iN − i + 1
14
23
32
41
Approach 2Count the rows down
The idea

Let i go from N down to 1 and print i stars.

JavaScript
const N = 4;for (let i = N; i >= 1; i--) {  let row = "";  for (let j = 1; j <= i; j++) {    row += "*";  }  console.log(row);}/* Output:***********/
How it works

This is the triangle from question 2, with the outer loop reversed. It is often the easiest way to turn a pattern upside down.

Which approach should you use?

Both are correct. Pick the rule that you can explain most easily. Approach 2 is usually quicker to write.

Q6Centred pyramidMedium

Print a pyramid of stars, with each row centred.

Example 1
Input: N = 4
Output:
   *
  ***
 *****
*******
Explanation: Row i has N − i spaces, then 2i − 1 stars: 3+1, 2+3, 1+5, 0+7.
Stuck? Open one hint at a time
Hint 1
Each row has two parts: some spaces, then some stars.
Hint 2
Fill in a table for rows 1 to 4 with the number of spaces and stars. Find a formula that uses i for each column of the table.
Hint 3
Spaces = N − i. Stars = 2i − 1. Use two inner loops, one after the other.
Show all 3 solutions with explanations
Approach 1Two inner loops: spaces, then stars
The idea

For each row, first add N − i spaces, then 2i − 1 stars.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let s = 1; s <= N - i; s++) row += " ";       // spaces  for (let k = 1; k <= 2 * i - 1; k++) row += "*";   // stars  console.log(row);}/* Output:   *  *** *************/
How it works
Dry run · pyramid, N = 4
ispaces = N − istars = 2i − 1
131
223
315
407
Approach 2Visit every cell and decide
The idea

The pyramid fits in a grid that is 2N − 1 columns wide. A cell gets a star if its distance from the centre column is less than i. Otherwise it gets a space.

JavaScript
const N = 4;const width = 2 * N - 1;const centre = N;                      // columns are numbered 1..widthfor (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= width; j++) {    row += Math.abs(j - centre) < i ? "*" : " ";  }  console.log(row.trimEnd());}/* Output:   *  *** *************/
How it works

Math.abs(j - centre) is how far column j is from the centre (Math.abs removes a minus sign, so the distance is never negative). In row 1, only the centre itself (distance 0) gets a star. In row 4, every column with a distance of up to 3 gets one.

Approach 3repeat
The idea

Build each row from two repeated pieces of text: spaces and stars.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  console.log(" ".repeat(N - i) + "*".repeat(2 * i - 1));}/* Output:   *  *** *************/
How it works

These are the same formulas as in Approach 1, but you do not write the inner loops yourself.

Which approach should you use?

Approach 1 is the standard answer. Approach 2 is a powerful general technique. For any shape, ask: “for cell (i, j), what belongs here?”

Q7Hollow squareMedium

Print the border of an N × N square, with spaces inside.

Example 1
Input: N = 4
Output:
****
*  *
*  *
****
Explanation: Stars only on the border: the first and last row, and the first and last column.
Stuck? Open one hint at a time
Hint 1
Visit every cell of the N × N grid.
Hint 2
A cell is on the border if it is in the first or last row, or in the first or last column. Print a star there and a space everywhere else.
Show all 2 solutions with explanations
Approach 1Decide for every cell
The idea

Loop over every (row, column) cell and print a star only on the border.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= N; j++) {    const onBorder = i === 1 || i === N || j === 1 || j === N;    row += onBorder ? "*" : " ";  }  console.log(row);}/* Output:*****  **  ******/
How it works

This “what belongs in cell (i, j)?” approach works for every pattern. You will use it for matrices (grids of numbers) in Lesson 25.

Approach 2Build the two kinds of row
The idea

There are only two kinds of row: a full row of stars, and a row with a star at each end and spaces in between.

JavaScript
const N = 4;const full = "*".repeat(N);const middle = N === 1 ? "*" : "*" + " ".repeat(N - 2) + "*";for (let i = 1; i <= N; i++) {  console.log(i === 1 || i === N ? full : middle);}/* Output:*****  **  ******/
How it works

Each kind of row is built once. The check for N === 1 handles an edge case (an unusual input). With N = 1, N - 2 would be −1, and repeat would throw an error.

Which approach should you use?

Approach 1 is the general method, and it handles N = 1 by itself. Approach 2 is faster to run, but you must think about the edge case.

Q8Floyd's triangleEasy

Fill a right triangle with consecutive numbers (1, 2, 3, and so on) starting at 1.

Example 1
Input: N = 4
Output:
1
2 3
4 5 6
7 8 9 10
Explanation: The numbers keep counting from row to row: row 2 continues where row 1 stopped.
Stuck? Open one hint at a time
Hint 1
The shape is the right triangle. The numbers do not start again in each row.
Hint 2
Keep one counter that is declared outside both loops. Add 1 to it after every number you print.
Show all 2 solutions with explanations
Approach 1A counter outside both loops
The idea

Print the counter in every cell. Increase it after each number.

JavaScript
const N = 4;let num = 1;                       // lives outside both loopsfor (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= i; j++) {    row += num + " ";    num++;  }  console.log(row.trimEnd());}/* Output:12 34 5 67 8 9 10*/
How it works

If num were declared inside the outer loop, it would go back to 1 in every row. The place where you declare a variable decides how long it keeps its value.

Approach 2Calculate the first number of each row
The idea

Before row i there are 1 + 2 + … + (i − 1) = i(i − 1)/2 numbers. So row i starts at i(i − 1)/2 + 1.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  const start = (i * (i - 1)) / 2 + 1;  let row = "";  for (let j = 0; j < i; j++) {    row += start + j + " ";  }  console.log(row.trimEnd());}/* Output:12 34 5 67 8 9 10*/
How it works

Row 4 starts at 4 × 3 / 2 + 1 = 7. This version can print any single row without working out the rows before it.

Which approach should you use?

Approach 1 is the simplest. Approach 2 uses the sum formula from Lesson 4. It is useful if you need only one row.

Q90-1 triangleMedium

Print a triangle of alternating 1s and 0s, as in the example.

Example 1
Input: N = 4
Output:
1
0 1
1 0 1
0 1 0 1
Explanation: The values alternate between 1 and 0. A cell holds 1 when its row number plus its column number is even.
Stuck? Open one hint at a time
Hint 1
Write the row number and the column number for a few cells and add them. When is the value 1?
Hint 2
Value = 1 if (i + j) % 2 === 0, otherwise 0.
Show all 2 solutions with explanations
Approach 1Formula from (i + j)
The idea

Cell (i, j) holds 1 when i + j is even and 0 when it is odd.

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let row = "";  for (let j = 1; j <= i; j++) {    row += ((i + j) % 2 === 0 ? 1 : 0) + " ";  }  console.log(row.trimEnd());}/* Output:10 11 0 10 1 0 1*/
How it works

Cell (1,1): 1 + 1 = 2, which is even, so the value is 1. Cell (2,1): 3 is odd, so the value is 0. Cell (2,2): 4 is even, so the value is 1. It is the same rule that colours a chessboard.

Approach 2Start value per row, then flip
The idea

Odd rows start with 1 and even rows start with 0. After each number, flip the value (1 becomes 0, and 0 becomes 1).

JavaScript
const N = 4;for (let i = 1; i <= N; i++) {  let value = i % 2 === 1 ? 1 : 0;  let row = "";  for (let j = 1; j <= i; j++) {    row += value + " ";    value = 1 - value;          // flip  }  console.log(row.trimEnd());}/* Output:10 11 0 10 1 0 1*/
How it works

1 - value turns 1 into 0 and 0 into 1. The code follows the pattern in the same way as you would describe it in words.

Which approach should you use?

Both are correct. Approach 1 shows the habit of looking for a formula that uses (i, j). Approach 2 is easier to find by looking at the output.

Q10Count the pairsMedium

How many pairs (i, j) are there with 1 ≤ i < j ≤ N?

Example 1
Input: N = 4
Output: 6
Explanation: The pairs are (1,2) (1,3) (1,4) (2,3) (2,4) (3,4).
Stuck? Open one hint at a time
Hint 1
For each first number i, which second numbers j are allowed?
Hint 2
Start the inner loop at i + 1. Then j is always bigger than i, and no pair is counted twice.
Show all 2 solutions with explanations
Approach 1Nested loops, inner starts at i + 1
The idea

For each i, count every j from i + 1 to N.

JavaScript
function countPairs(N) {  let count = 0;  for (let i = 1; i <= N; i++) {    for (let j = i + 1; j <= N; j++) {      count++;    }  }  return count;}console.log(countPairs(4)); // 6console.log(countPairs(5)); // 10
How it works

This is the shape of every brute-force “compare every pair” solution. Brute force means trying every possibility. An example is the first approach to Two Sum (Lesson 26).

Approach 2Formula N × (N − 1) / 2
The idea

Number 1 pairs with N − 1 others, number 2 with N − 2 others, and so on. The total is (N − 1) + … + 1 = N(N − 1)/2.

JavaScript
function countPairs(N) {  return (N * (N - 1)) / 2;}console.log(countPairs(4)); // 6console.log(countPairs(5)); // 10
How it works

This is the sum formula from Lesson 4 again. The count grows like N², which is a hint that comparing every pair becomes very slow for large N.

Which approach should you use?

If you only need the count, use the formula. If you need to do something with each pair, you need the loops. This is why Part 4 teaches ways to avoid checking every pair.

Q11Pascal's triangleMedium

Print the first N rows of Pascal's triangle.

Example 1
Input: N = 5
Output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
Explanation: Each row starts and ends with 1. Every number in the middle is the sum of the two numbers above it, for example 3 = 1 + 2.
Stuck? Open one hint at a time
Hint 1
Each row can be built from the row above it.
Hint 2
Keep the previous row in a list. The new row is 1, then the sums of neighbouring pairs from the previous row, then 1 again.
Show all 2 solutions with explanations
Approach 1Build each row from the previous one
The idea

Keep the previous row as an array (a list). For the new row, add neighbouring pairs from the previous row, and put 1 at both ends.

JavaScript
const N = 5;let prev = [];for (let i = 0; i < N; i++) {  const row = [1];  for (let j = 1; j < i; j++) {    row.push(prev[j - 1] + prev[j]);    // the two numbers above  }  if (i > 0) row.push(1);  console.log(row.join(" "));  prev = row;}/* Output:11 11 2 11 3 3 11 4 6 4 1*/
How it works

This uses arrays from Lesson 8. push adds an item to the end. prev[j] reads the item at a position. join(" ") turns the row into text. This is LeetCode 118.

Approach 2Calculate each number directly
The idea

The numbers in row i are “i choose 0”, “i choose 1” and so on. “i choose k” is the number of ways to pick k items from i items. Each number can be worked out from the one before it: next = current × (i − k) / (k + 1).

JavaScript
const N = 5;for (let i = 0; i < N; i++) {  let value = 1;  let row = "";  for (let k = 0; k <= i; k++) {    row += value + " ";    value = (value * (i - k)) / (k + 1);  }  console.log(row.trimEnd());}/* Output:11 11 2 11 3 3 11 4 6 4 1*/
How it works

For row 4 (counting rows from 0, so this is the fifth row): 1, then 1 × 4 / 1 = 4, then 4 × 3 / 2 = 6, then 6 × 2 / 3 = 4, then 4 × 1 / 4 = 1. You do not need to store the previous row.

Which approach should you use?

Approach 1 is the answer interviewers expect, and it is easier to explain. Approach 2 is a short maths option that needs no extra list.

Make it stick

Make it stick — close this page, then
  1. Say the rule out loud: “for every iteration of the outer loop, the inner loop runs…”
  2. Without looking, write the pyramid for N = 3 and its table of spaces and stars.
  3. Explain where let row = "" and console.log(row) must go, and what goes wrong if either moves.

Revisit schedule: solve two of the questions again tomorrow, again in 3 days, and once more in a week — without looking at the answers. Each time it will feel easier. That is the memory forming.

Next lesson: functions. A function packs code into a named block so you can reuse it. It is also the format of every interview answer.

Practise on LeetCode

Real interview problems that use exactly what this lesson teaches. Solve them in JavaScript after the practice questions above.

Published by Jainik · Last updated · How these lessons are made

Keep learning

Related series