In this lesson, we'll cover:
- Why nested loops are used with 1D and 2D arrays
- How to build nested loop algorithms step-by-step
- How 2D arrays are structured internally
- How to read values, modify values, and traverse grids
- How to avoid common mistakes
- A repeatable debugging process for 2D array logic
A set of practice problems follows.
Recall a nested loop is a loop written inside another loop. The inner loop completes entirely for every single iteration of the outer loop.
Example:
for (int i = 0; i < 3; i++) {
System.out.println("Outer loop i = " + i);
for (int j = 0; j < 2; j++) {
System.out.println(" Inner loop j = " + j);
}
}Outer loop i = 0
Inner loop j = 0
Inner loop j = 1
Outer loop i = 1
Inner loop j = 0
Inner loop j = 1
Outer loop i = 2
Inner loop j = 0
Inner loop j = 1
Notice:
- The inner loop runs multiple times per outer-loop iteration.
- Nested loops allow us to compare pairs, generate combinations, or revisit the entire array repeatedly.
Arrays sometimes require nested loops when:
- You compare each value to every other value
- You generate pairings
- You run a full scan inside another scan
- You need “all combinations” of elements
int[] nums = {4, 7, 2};
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
System.out.println(nums[i] + ", " + nums[j]);
}
}4, 4
4, 7
4, 2
7, 4
7, 7
7, 2
2, 4
2, 7
2, 2
boolean hasDuplicate = false;
int[] nums = {4, 7, 2, 7};
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] == nums[j]) {
hasDuplicate = true;
}
}
}
System.out.println(hasDuplicate);true
To avoid comparing:
- The same pair twice (e.g., comparing index 2 with index 0 after index 0 with index 2)
- An element with itself
- The outer loop chooses an element.
- The inner loop processes related elements.
- Limiting the inner loop (e.g.,
j = i + 1) avoids repetition. - Nested loops grow in runtime quickly; understanding structure is important.
A 2D array is an array of arrays. Conceptually, you can think of it as:
- A grid
- A table
- A matrix
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};Row 0: 1 2 3
Row 1: 4 5 6
grid
├── grid[0] → {1, 2, 3}
└── grid[1] → {4, 5, 6}
Each row is another array — a 1D array.
Use:
grid[row][column]
Example:
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
int x = grid[0][2]; // retrieves 3grid.lengthgrid[r].lengthRows may not be equal length.
This is called a jagged array.
This means:
for each row → visit each column
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.println("Row " + r + ", Col " + c + ": " + grid[r][c]);
}
}Row 0, Col 0: 1
Row 0, Col 1: 2
Row 0, Col 2: 3
Row 1, Col 0: 4
Row 1, Col 1: 5
Row 1, Col 2: 6
This algorithm uses a row-major traversal of a 2D array along with an accumulator variable, sum.
int sum = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
sum += grid[r][c];
}
}This algorithm uses the same row-major traversal as above, but adds a counter variable and a modulus operation.
int count = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] % 2 == 0) {
count++;
}
}
}Less common but still useful. If a 2D array is laid out as a grid, column-major traversal enables totalling vertical columns, for example.
for (int c = 0; c < grid[0].length; c++) {
for (int r = 0; r < grid.length; r++) {
System.out.println(grid[r][c]);
}
}Enhanced loops simplify syntax:
for (int[] row : grid) {
for (int value : row) {
System.out.println(value);
}
}- Cleaner and readable
- Cannot access row/column index easily
This confirms the row x column size of the grid with which you're working:
System.out.println("Rows: " + grid.length);
System.out.println("Cols in row 0: " + grid[0].length);Inside loops, show the current row x column value before doing something with that data:
System.out.println("Visiting (" + r + ", " + c + ")");Many logic errors disappear when you visualize the structure:
c0 c1 c2 c3 c4
+----+----+----+----+----+
r0 | | | | | |
+----+----+----+----+----+
r1 | | | | | |
+----+----+----+----+----+
Example:
1 2
3 4
Small grids reveal patterns easily.
- Using
grid.lengthfor row and column loops - Forgetting
grid[r].lengthfor the inner loop - Mixing up row and column
- Off-by-one errors
- Assuming every row has the same number of columns
- Trying to access
grid[r][c]before confirming row/column length
Work through these in order to build confidence with nested loops, 1D comparisons, and 2D traversal. The problem set is subdivided into 3 sections of 5 problems each.
Annotated solutions to these problems can be found here.
Starter array:
int[] nums = {4, 2, 9};Task:
Use nested loops to print each value three times on the same line, prefixed by its index.
Expected Output:
Index 0: 4 4 4
Index 1: 2 2 2
Index 2: 9 9 9
Starter array:
int[] nums = {3, 6};Task:
Using two nested loops, print every ordered pair (nums[i], nums[j]).
Expected Output:
(3, 3)
(3, 6)
(6, 3)
(6, 6)
Starter array:
int[] nums = {7, 1, 7, 3, 7};Task:
Count how many times the value at index 0 appears again later in the array.
Expected Output:
2
Starter array:
int[] nums = {8, 5, 2};Task:
Using nested loops, print all pairs (nums[i], nums[j]) where nums[j] > nums[i].
Expected Output:
(5, 8)
(2, 8)
(2, 5)
Starter array:
int[] nums = {4, 5, 7, 8};Task:
Count how many index pairs (i, j) produce values whose difference is exactly 1.
Expected Output:
Pairs differing by 1: 2
Starter grid:
int[][] grid = {
{2, 4},
{6, 8, 10},
{5}
};Task:
Print the total row count, and then print the number of columns in each row.
Expected Output:
Row count: 3
Row 0 has 2 columns
Row 1 has 3 columns
Row 2 has 1 column
Starter grid:
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};Task:
Use nested loops to print the grid in table form.
Expected Output:
1 2 3
4 5 6
Starter grid:
int[][] grid = {
{3, 1},
{2, 9}
};Task: Compute the sum of each row and print it.
Expected Output:
Row 0 sum: 4
Row 1 sum: 11
Starter grid:
int[][] grid = {
{2, 3, 4},
{5, 6, 7}
};Task:
Use column-major traversal to compute the sum of each column.
Expected Output:
Column 0 sum: 7
Column 1 sum: 9
Column 2 sum: 11
Starter grid:
int[][] grid = {
{4, 11, 9},
{15, 2, 7}
};Task:
Count all values strictly greater than 10.
Expected Output:
Values > 10: 2
Starter grid:
int[][] grid = {
{4, 8, 1},
{3, 18, 6},
{7, 2, 5}
};Task:
Scan the entire grid to find the maximum value.
Expected Output:
Max value: 18
Starter grid:
int[][] grid = {
{2, 5, 9},
{4, 6, 8},
{1, 3, 7}
};Task:
For each row, count how many values are even.
Expected Output:
Row 0 evens: 1
Row 1 evens: 3
Row 2 evens: 0
Starter grid:
int[][] grid = {
{2, 5, 9},
{3, 3, 8},
{1, 4, 7}
};Task:
A row is “strictly increasing” if every value is greater than the one before it.
Expected Output:
Row 0 is strictly increasing
Row 2 is strictly increasing
Starter grid:
int[][] grid = {
{0, 2, 0},
{1, 1, 1},
{3, 3, 3}
};Task:
Count how many values equal their row index.
Expected Output:
Matches row index: 5
Starter grid:
int[][] grid = {
{4, 8, 1},
{3, 9, 6},
{7, 2, 5}
};Task:
Given a target value, scan the grid and print the location of the first match.
If the target does not appear, print “Not found.”
Example Target:
9
Expected Output:
Found at row 1, column 1