Two-dimensional arrays

Marks of a whole class, seats in a bus, sales of every store for every week: some data is a table. A 2D array stores it with two indexes, row and column. You'll learn the secret that Java's 2D arrays are really arrays of arrays, why rows can have different lengths, how to loop over rows and columns, and then practise with 11 problems.

Module 4 · Arrays and Strings⏱ 24 minBeginner11 practice problems
1 The story

The whole class's marksheet

Riya's report-card program works for one student. Now the class teacher wants it for everyone: 3 students, 4 subjects each. Riya starts writing marksRiya, marksKabir, marksMeera… and stops. There are 60 students in the real class.

MathsScienceEnglishHindi [0][1][2][3] Riya [0]Kabir [1]Meera [2] 78926588 81679074 95887991 marks[1][2] row 1 (Kabir), column 2 (English) myphatshala.in
Riya

Sir, it's a table: students down, subjects across. Can one array hold a whole table?

Arjun Sir

Yes, with two indexes: marks[student][subject]. Kabir's English is marks[1][2]: row first, then column.

Riya

So Java stores a grid of boxes?

Arjun Sir

Here's the secret: Java has no real grid. A 2D array is an array whose elements are themselves arrays, one per row. That's why marks[1] on its own is a whole row, and why rows can even have different lengths.

2 Definition

What is a two-dimensional array?

Formal definition (write this in exams)

A two-dimensional array in Java is an array of arrays: a one-dimensional array whose elements are references to other one-dimensional arrays (the rows). An element is accessed with two indexes, a[row][col]. Because each row is a separate array object, rows may have different lengths; such an array is called a jagged (or ragged) array.

In simple words

A list of rows, where each row is a normal array. First pick the row, then the box inside that row.

Words you'll meet in this lesson

RowOne inner array: a[r].
ColumnThe same position across all rows: a[0][c], a[1][c] …
MatrixA rectangular 2D array: every row has the same length.
Jagged arrayA 2D array whose rows have different lengths.
Row-majorVisiting a table row by row, left to right: the natural order for Java.
Deep copyCopying the rows too, not just the outer array of references.

2D array facts at a glance

Create rectangularint[][] a = new int[3][4]; → 3 rows × 4 columns, all 0
Create with valuesint[][] a = {{1, 2, 3}, {4, 5, 6}};
Number of rowsa.length
Length of row ra[r].length (use this, not a fixed number)
Jaggedint[][] a = new int[3][]; then a[0] = new int[2]; … (rows start as null)
PrintArrays.deepToString(a) → [[1, 2, 3], [4, 5, 6]]

Exam tip: the first size is required, the second is optional: new int[3][] compiles, new int[][3] does not. Also, new int[3][4] creates 4 objects: one outer array and three rows.

3 Types and ways to use it

Rectangular and jagged arrays

Rectangular (matrix)

Every row has the same number of columns. Marksheets, seat maps, game boards, images.

new int[rows][cols]

Jagged

Rows of different lengths: days in each month, orders per customer, seats per coach.

new int[rows][]

Rows are arrays

a[1] is a full int[]. You can pass it to a method, loop over it with for-each, or swap whole rows.

int[] row = a[1]

A jagged array in action

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] seats = new int[3][];        // 3 rows, not created yet
        System.out.println(Arrays.deepToString(seats));
        seats[0] = new int[1];
        seats[1] = new int[3];
        seats[2] = new int[2];
        System.out.println(Arrays.deepToString(seats));
        System.out.println("Row 1 has " + seats[1].length + " seats");
    }
}
[null, null, null] [[0], [0, 0, 0], [0, 0]] Row 1 has 3 seats

Which loop shape do I need?

TaskOuter loopInner loop
Print, row totals, searchrows: r < a.lengthcolumns: c < a[r].length
Column totalscolumns: c < a[0].lengthrows: r < a.length
Diagonal of a square matrixone loop: a[i][i] and a[i][n - 1 - i]
Just read every valuefor (int[] row : a)for (int x : row)

Copy trap: a.clone() and Arrays.copyOf(a, a.length) copy only the outer array. The new array points to the same rows, so changing copy[0][0] also changes a[0][0]. Copy each row for a real (deep) copy.

4 Step by step

Building and walking a 2D array

  1. Create the table

    int[][] grid = new int[3][4];
    The JVM creates an outer array of 3 references, then three int[4] row arrays filled with 0, and stores each row's address in the outer array.
  2. Read or write one cell

    grid[1][2] = 7;
    Two steps: grid[1] follows the outer array to row 1; [2] then picks index 2 in that row. Both indexes are bounds-checked.
  3. Loop over rows, then over each row

    for (int r = 0; r < grid.length; r++) {
        for (int c = 0; c < grid[r].length; c++) {
            System.out.print(grid[r][c] + " ");
        }
        System.out.println();
    }
    grid.length is the number of rows; grid[r].length is that row's length. This form works for rectangular and jagged arrays alike.
  4. Or use for-each when you only read

    for (int[] row : grid) {
        for (int value : row) total += value;
    }
    The outer for-each hands you each row as an int[]. That's the array-of-arrays idea made visible.
  5. Print it for debugging

    System.out.println(Arrays.deepToString(grid));
    Arrays.toString(grid) would print three row references like [I@1b6d3586; deepToString goes inside each row.
5 See it happen

The array-of-arrays secret: both views

Left: the code and what it prints. Right: the outer array of references and the row arrays it points to.

Inside int[][] 6 steps
What you see int[][] grid = new int[3][4]; grid[1][2] = 7; grid.length; grid[1].length; for r { for c { print(grid[r][c]) } } int[][] seats = new int[3][]; seats[0] = new int[2]; …[4]; …[3]; [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] grid[1][2] → 7 grid.length → 3 (rows) grid[1].length → 4 (columns) 0 0 0 0 0 0 7 0 0 0 0 0 [null, null, null] [[0, 0], [0, 0, 0, 0], [0, 0, 0]] Looks like a 3 × 4 table of zeros. Row first, then column. Two different lengths. Row by row, left to right. Rows not created yet. Three rows, three different lengths. myphatshala.in
Behind the screen grid seats outer [0][1][2] nullnullnull [0][1][2][3] 0000 000 0000 0 7 grid.length = 3 grid[1].length = 4 00 0000 000 len 2len 4len 3 4 objects: 1 outer array + 3 row arrays. grid[1] → row 1, then [2] inside that row. Outer length = rows; each row has its own length. Row-major order: finish a row, then go down. Only the outer array exists. Rows are null. Each reference points to a row of its own size. myphatshala.in
6 Real-world use

2D arrays in real systems

Whenever data has rows and columns, a 2D array (or something built like one) is behind it.

Watch it with an example: a class marks sheet

3 students × 3 subjects in one int[][]. Watch the nested loops add each row, and see how Java really stores it: an array of row arrays.

int[][] marks = new int[3][3] 6 steps
Animated example Maths Phys Chem Total Riya 78 85 90 253 Kabir 65 70 72 207 Asha 88 92 95 275 r = 0 r = 1 r = 2 Topper: Asha (275) marks [0] → row {78, 85, 90} [1] → row {65, 70, 72} [2] → row {88, 92, 95} each row is its own int[] object myphatshala.in

1. Seat maps

Cinema halls, buses and flights keep seat status in a grid: seat[row][col]. Different coach types, with different seats per row, are a natural jagged array.

Seat status→boolean[][] booked→Seat picker

2. Reports and pivot tables

Sales by store and week, attendance by student and day, expenses by month and category: rows, columns, and totals along each.

Raw records→int[stores][weeks]→Summary table
[y][x]

3. Images

A grayscale image is a 2D array of brightness values, pixel[y][x]. Filters like blur and sharpen loop over every row and column.

Photo→int[height][width]→Filtered photo
XO

4. Game boards and maps

Tic-tac-toe, chess, Sudoku, and the tile maps of 2D games are grids. Checking a row, column or diagonal for a win is a 2D-array loop.

Moves→char[3][3] board→Winner check

Examples are simplified. Large tables usually live in a database or spreadsheet, and are loaded into arrays or lists for processing.

7 Run the code

The class marksheet

public class Main {
    public static void main(String[] args) {
        String[] students = {"Riya", "Kabir", "Meera"};
        int[][] marks = {
            {78, 92, 65, 88},
            {81, 67, 90, 74},
            {95, 88, 79, 91}
        };
        for (int s = 0; s < marks.length; s++) {
            int total = 0;
            for (int sub = 0; sub < marks[s].length; sub++) {
                total += marks[s][sub];
            }
            System.out.println(students[s] + " total: " + total);
        }
        System.out.println("Kabir's English: " + marks[1][2]);
    }
}
Riya total: 323 Kabir total: 312 Meera total: 353 Kabir's English: 90
  • int[][] marks = { {…}, {…}, {…} };Each inner pair of braces is one row (one student).
  • String[] studentsA parallel array: students[s] names row s.
  • int total = 0; inside the outer loopReset for every student, otherwise totals pile up.
  • marks[s].lengthThe number of subjects in this student's row.
8 Line by line

Summing a 2 × 2 matrix

Watch r stay put while c runs across each row, and the three objects on the heap.

Worked examples: real problems, solved and traced in memory

Three real problems that need rows and columns. Run each solution, then step through it to watch the outer array, the row arrays and every method call in memory.

Example 1Retail chain · weekly report

Total sales per store

Problem statement

A chain has 2 stores. Their sales (in ₹ thousands) for 3 weeks are kept in a 2D array, one row per store. Print each store's total using a helper method that adds up one row.

Input
sales = {{120, 135, 110}, {90, 95, 100}}
Expected output
Store 1: 365
Store 2: 285

Approach

  1. Each row of a 2D array is itself an int[], so a method that sums an int[] can sum a row.
  2. Loop over the rows with s; pass sales[s] (one row) to rowTotal.
  3. Print the returned total for each store.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Cinema · seat booking

Book a seat, refuse if taken

Problem statement

A small screen has 2 rows of 3 seats. A method book(seats, row, col) must mark a free seat as booked and return true, or return false if someone already has it. Try booking row 1 seat 2, the same seat again, then row 0 seat 0.

Input
seats = new boolean[2][3] (all free)
requests: (1, 2), (1, 2), (0, 0)
Expected output
R1 S2: true
R1 S2 again: false
R0 S0: true

Approach

  1. Use boolean[][]: false = free (the default), true = booked.
  2. In book, check seats[row][col]; if already true, return false.
  3. Otherwise set it to true and return true. The change is made in the shared array, so main sees it.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3School · class results

Average marks in classes of different sizes

Problem statement

Class A has 2 students and class B has 3. Their marks are stored in a jagged array (rows of different lengths). Print each class's average mark.

Input
marks = {{70, 80}, {90, 60, 75}}
Expected output
Class A: 75.0
Class B: 75.0

Approach

  1. A jagged array lets each row (class) have its own length.
  2. For row c, loop up to marks[c].length, not a fixed number.
  3. Average = row sum / row length, as a double.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 4.2 in one screen

  • A 2D array is an array of arrays: an outer array of row references.
  • a[row][col]: row first. a.length = rows, a[r].length = that row's columns.
  • new int[r][c] → r + 1 objects, all zeros. new int[r][] → rows are null (jagged).
  • Traverse: outer over rows, inner up to a[r].length. Columns first for column totals.
  • Diagonals need one loop: a[i][i], a[i][n-1-i].
  • Print with Arrays.deepToString.
  • clone() / copyOf are shallow; copy every row for a deep copy.

Interview and viva questions

Are Java 2D arrays stored as one block of memory?

No. Unlike C, Java stores a 2D array as an outer array of references, each pointing to a separate row array. Rows may be anywhere on the heap and may have different lengths.

What is a jagged array and when is it useful?

A 2D array whose rows have different lengths, created as new int[n][] with each row created separately. Useful for naturally uneven data: days per month, items per order, seats per coach. It saves memory compared with padding every row to the longest length.

How do you deep-copy a 2D array?

Create a new outer array, then copy each row: for (int r = 0; r < a.length; r++) copy[r] = a[r].clone();. For arrays of objects, you'd also need to copy the objects themselves.

Why is row-by-row traversal usually faster than column-by-column?

Each row is a contiguous array, so reading along a row uses memory that is already in the CPU cache. Going down a column jumps between different row objects every step. For big matrices the difference can be noticeable.

How do you pass a 2D array to a method and what can the method change?

Declare the parameter as int[][] a. The method receives a copy of the reference, so it can change any element (and even replace rows) of the caller's array, but reassigning a itself inside the method doesn't affect the caller.

Practice problems

Matrix problems appear in almost every campus test. For each one, first decide: do I go row by row, column by column, or along a diagonal? The last three are real business tasks.

P1Easy

Print a matrix as a grid

Print a 2D array as rows and columns, with values separated by tabs.

Input
m = {{1, 2, 3}, {4, 5, 6}}
Expected output
1	2	3	
4	5	6	
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] m = {{1, 2, 3}, {4, 5, 6}};
        for (int r = 0; r < m.length; r++) {
            for (int c = 0; c < m[r].length; c++) {
                System.out.print(m[r][c] + "\t");
            }
            System.out.println();
        }
    }
}
1 2 3 4 5 6

How it works: the outer loop picks a row, the inner loop walks across it. Using m[r].length (not a fixed number) keeps it correct for jagged arrays too. println() after the inner loop ends each row.

P2Easy

Row sums

Print the total of each row.

Input
m = {{3, 5, 2}, {7, 1, 4}, {6, 6, 6}}
Expected output
Row 0 sum = 10
Row 1 sum = 12
Row 2 sum = 18
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] m = {{3, 5, 2}, {7, 1, 4}, {6, 6, 6}};
        for (int r = 0; r < m.length; r++) {
            int sum = 0;
            for (int c = 0; c < m[r].length; c++) {
                sum += m[r][c];
            }
            System.out.println("Row " + r + " sum = " + sum);
        }
    }
}
Row 0 sum = 10 Row 1 sum = 12 Row 2 sum = 18

How it works: reset sum to 0 at the start of every row, inside the outer loop. Declaring it outside both loops is the most common bug: the totals would keep piling up.

P3Easy

Column sums

Print the total of each column.

Input
m = {{3, 5, 2}, {7, 1, 4}, {6, 6, 6}}
Expected output
Column 0 sum = 16
Column 1 sum = 12
Column 2 sum = 12
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] m = {{3, 5, 2}, {7, 1, 4}, {6, 6, 6}};
        for (int c = 0; c < m[0].length; c++) {
            int sum = 0;
            for (int r = 0; r < m.length; r++) {
                sum += m[r][c];
            }
            System.out.println("Column " + c + " sum = " + sum);
        }
    }
}
Column 0 sum = 16 Column 1 sum = 12 Column 2 sum = 12

How it works: swap the loops: the outer loop goes over columns, the inner over rows. The index order m[r][c] stays the same; only the loop order changes. This assumes a rectangular matrix.

P4Easy

Diagonal sums

For a square matrix, find the sum of the main diagonal (top-left to bottom-right) and the other diagonal.

Input
m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
Expected output
Main diagonal: 15
Other diagonal: 15
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        int n = m.length, main = 0, other = 0;
        for (int i = 0; i < n; i++) {
            main += m[i][i];
            other += m[i][n - 1 - i];
        }
        System.out.println("Main diagonal: " + main);
        System.out.println("Other diagonal: " + other);
    }
}
Main diagonal: 15 Other diagonal: 15

How it works: on the main diagonal row and column are equal, [i][i]. On the other diagonal they add up to n − 1, so the column is n - 1 - i. One loop is enough; no nested loop needed.

P5Medium

Add two matrices

Add two matrices of the same size element by element into a new matrix.

Input
a = {{1, 2}, {3, 4}}, b = {{10, 20}, {30, 40}}
Expected output
[[11, 22], [33, 44]]
Show solution and explanation
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] a = {{1, 2}, {3, 4}};
        int[][] b = {{10, 20}, {30, 40}};
        int[][] sum = new int[a.length][a[0].length];
        for (int r = 0; r < a.length; r++) {
            for (int c = 0; c < a[0].length; c++) {
                sum[r][c] = a[r][c] + b[r][c];
            }
        }
        System.out.println(Arrays.deepToString(sum));
    }
}
[[11, 22], [33, 44]]

How it works: create the result with the same dimensions, then fill each cell from the matching cells of a and b. Arrays.deepToString prints nested arrays; Arrays.toString would print only the row references.

P6Medium

Transpose a matrix

Turn rows into columns: a 2 × 3 matrix becomes 3 × 2.

Input
m = {{1, 2, 3}, {4, 5, 6}}
Expected output
[[1, 4], [2, 5], [3, 6]]
Show solution and explanation
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[][] m = {{1, 2, 3}, {4, 5, 6}};
        int[][] t = new int[m[0].length][m.length];
        for (int r = 0; r < m.length; r++) {
            for (int c = 0; c < m[0].length; c++) {
                t[c][r] = m[r][c];
            }
        }
        System.out.println(Arrays.deepToString(t));
    }
}
[[1, 4], [2, 5], [3, 6]]

How it works: the result has the dimensions swapped: new int[cols][rows]. Each value moves from [r][c] to [c][r].

P7Medium

Largest value in each row

Print the highest value in each row of a jagged array (rows of different lengths).

Input
scores = {{45, 80}, {72, 91, 60}, {55}}
Expected output
Row 0: 80
Row 1: 91
Row 2: 55
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] scores = {{45, 80}, {72, 91, 60}, {55}};
        for (int r = 0; r < scores.length; r++) {
            int max = scores[r][0];
            for (int c = 1; c < scores[r].length; c++) {
                if (scores[r][c] > max) max = scores[r][c];
            }
            System.out.println("Row " + r + ": " + max);
        }
    }
}
Row 0: 80 Row 1: 91 Row 2: 55

How it works: each row is its own array with its own length, so the inner loop must use scores[r].length. Using scores[0].length would skip values in row 1 and crash on row 2.

P8Medium

Search in a matrix

Find the row and column of a value, or report that it isn't there. Stop as soon as it's found.

Input
m = {{4, 9, 2}, {7, 5, 8}}, target = 5
Expected output
Found at row 1, column 1
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int[][] m = {{4, 9, 2}, {7, 5, 8}};
        int target = 5;
        boolean found = false;
        search:
        for (int r = 0; r < m.length; r++) {
            for (int c = 0; c < m[r].length; c++) {
                if (m[r][c] == target) {
                    System.out.println("Found at row " + r + ", column " + c);
                    found = true;
                    break search;
                }
            }
        }
        if (!found) System.out.println("Not found");
    }
}
Found at row 1, column 1

How it works: a labelled break (Lesson 3.5) leaves both loops at once. The found flag tells us afterwards whether to print “Not found”.

P9Business problem

Store × week sales report

A chain has 3 stores. Sales (in ₹ thousands) for 4 weeks are in a 2D array, one row per store. Print each store's total, each week's total and the best store.

Input
sales = {{120, 135, 110, 150}, {90, 95, 100, 98}, {160, 140, 155, 170}}
Expected output
Andheri: 515
Pune: 383
Indiranagar: 625
Week totals: 370 370 365 418
Best store: Indiranagar
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        String[] stores = {"Andheri", "Pune", "Indiranagar"};
        int[][] sales = {{120, 135, 110, 150}, {90, 95, 100, 98}, {160, 140, 155, 170}};
        int best = 0, bestTotal = -1;
        for (int s = 0; s < sales.length; s++) {
            int total = 0;
            for (int w = 0; w < sales[s].length; w++) total += sales[s][w];
            System.out.println(stores[s] + ": " + total);
            if (total > bestTotal) { bestTotal = total; best = s; }
        }
        System.out.print("Week totals:");
        for (int w = 0; w < sales[0].length; w++) {
            int total = 0;
            for (int s = 0; s < sales.length; s++) total += sales[s][w];
            System.out.print(" " + total);
        }
        System.out.println();
        System.out.println("Best store: " + stores[best]);
    }
}
Andheri: 515 Pune: 383 Indiranagar: 625 Week totals: 370 370 365 418 Best store: Indiranagar

How it works: a parallel 1D array stores holds the names, so stores[s] labels row s. Row totals walk across; week totals walk down. This is exactly what a spreadsheet pivot table does.

P10Business problem

Bus seat booking map

A bus has 5 rows of 4 seats. true means booked. Print the seat map (X = booked, _ = free), count free seats, and book the first free window seat (columns 0 and 3).

Input
5 × 4 boolean array with some seats booked
Expected output
X X _ X 
X _ _ X 
_ _ X _ 
_ _ _ _ 
_ _ _ _ 
Free seats: 14
Booked window seat: row 3, seat 1
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        boolean[][] booked = new boolean[5][4];
        booked[0][0] = booked[0][1] = booked[0][3] = true;
        booked[1][0] = booked[1][3] = true;
        booked[2][2] = true;

        int free = 0;
        for (int r = 0; r < booked.length; r++) {
            for (int c = 0; c < booked[r].length; c++) {
                System.out.print(booked[r][c] ? "X " : "_ ");
                if (!booked[r][c]) free++;
            }
            System.out.println();
        }
        System.out.println("Free seats: " + free);

        windowSearch:
        for (int r = 0; r < booked.length; r++) {
            for (int c = 0; c < 4; c += 3) {
                if (!booked[r][c]) {
                    booked[r][c] = true;
                    System.out.println("Booked window seat: row " + (r + 1) + ", seat " + (c + 1));
                    break windowSearch;
                }
            }
        }
    }
}
X X _ X X _ _ X _ _ X _ _ _ _ _ _ _ _ _ Free seats: 14 Booked window seat: row 3, seat 1

How it works: a new boolean[][] starts all false (free). c += 3 visits only columns 0 and 3, the windows. Seat numbers shown to passengers are index + 1. Real booking apps use the same grid idea, with the database deciding who gets a seat when two people click together.

P11Business problem

Attendance shortage list

Rows are students, columns are 6 class days (1 = present, 0 = absent). Print each student's attendance percentage and flag anyone below 75%.

Input
att = {{1,1,1,1,0,1}, {1,0,0,1,0,1}, {1,1,1,1,1,1}}
Expected output
Riya    83.3%
Kabir   50.0%  << shortage
Meera  100.0%
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        String[] names = {"Riya", "Kabir", "Meera"};
        int[][] att = {{1, 1, 1, 1, 0, 1}, {1, 0, 0, 1, 0, 1}, {1, 1, 1, 1, 1, 1}};
        for (int s = 0; s < att.length; s++) {
            int present = 0;
            for (int d = 0; d < att[s].length; d++) present += att[s][d];
            double pct = present * 100.0 / att[s].length;
            String flag = pct < 75 ? "  << shortage" : "";
            System.out.printf("%-6s %5.1f%%%s%n", names[s], pct, flag);
        }
    }
}
Riya 83.3% Kabir 50.0% << shortage Meera 100.0%

How it works: with 1/0 values, the row sum is the number of days present. Multiplying by 100.0 forces decimal division. printf lines the names and percentages up in columns (%% prints a percent sign).

Real-world scenario questions (asked in company interviews)

Grid bugs are usually row/column mix-ups, uneven rows or shared rows. Decide your answer first, then open the model answer.

Media · image filtersFresher

Works on square photos, crashes on landscape ones

An image filter stores pixels as int[height][width]. It works on 500 × 500 test images, but crashes with ArrayIndexOutOfBoundsException on a 800 × 600 landscape photo. The loop is for (x < width) for (y < height) pixel[x][y]. What's wrong?

The interviewer is checking: do you keep row/column (y/x) order straight, and test with non-square data?

Show a strong answer
  • The array is [height][width], so it must be indexed pixel[y][x]. The code swaps them.
  • With square images, both dimensions are equal, so the bug is invisible. With 800 wide × 600 high, x reaches 600+ as a row index, and there are only 600 rows.
  • Fix the index order, loop rows (y) on the outside, and add a non-square test image to the test suite.

Avoid: testing only with square or symmetric data. It hides row/column mix-ups.

Retail · reportingFresher

New stores have fewer weeks of data

A report keeps weekly sales in sales[store][week]. Two stores opened recently, so their rows are shorter. The report now either crashes or misses weeks for older stores. The inner loop uses sales[0].length. Explain and fix.

The interviewer is checking: do you understand jagged arrays and per-row lengths?

Show a strong answer
  • Rows have different lengths now. Using row 0's length for every row overruns shorter rows (crash) or stops early on longer ones (missing data).
  • Use sales[s].length in the inner loop so each store uses its own number of weeks.
  • For week-wise totals across stores, check w < sales[s].length before reading, and decide with the business how to treat weeks before a store opened.

Avoid: padding rows with zeros without asking. Zero sales and “not open yet” mean different things in a report.

Gaming · undo feature1–3 years

Undo doesn't undo

A board game saves the board before every move with history.push(board.clone()), where board is a char[8][8]. When the player presses Undo, the restored board still shows the latest move. Why?

The interviewer is checking: do you know shallow vs deep copies of nested arrays?

Show a strong answer

clone() copied only the outer array of 8 row references. Every saved snapshot shares the same 8 row arrays as the live board, so each move changes all the “saved” boards too.

  • Deep-copy the rows: create a new char[8][] and set snapshot[r] = board[r].clone() for each row.
  • Alternatively, store the moves (from, to, captured piece) and reverse them, which uses far less memory.
  • Add a test: make a move, undo, and compare with the original board.

Avoid: assuming clone() copies everything. For nested arrays and objects it's shallow.

Analytics · performance3+ years

Same work, five times slower

Two versions of a job sum a 10,000 × 10,000 double[][]. Version A loops rows outside, columns inside. Version B loops columns outside, rows inside. Both are correct, but B is several times slower. Explain.

The interviewer is checking: do you understand memory layout and CPU caches?

Show a strong answer
  • Each row is a separate contiguous array. Version A reads each row from start to end, so the CPU fetches memory in cache lines and uses all of it.
  • Version B jumps to a different row object on every step, touching one value per cache line and constantly fetching new memory.
  • Prefer row-major traversal. If you truly need column-wise access often, store the data transposed, or as a single 1D array indexed r * cols + c.
  • Always measure with a proper benchmark before and after.

Avoid: saying “both are O(n²), so they're the same speed.” Big-O ignores memory effects.