Multi-dimensional arrays allow data to be stored and accessed in a structured grid-like format, making them ideal for representing complex tabular information in computer programs.
What are multi-dimensional arrays?
Two-dimensional arrays (2D arrays or matrices)
A two-dimensional array is a data structure that stores elements in a grid consisting of rows and columns. You can think of it as an array of arrays, where each sub-array represents one row. This structure allows for organised storage and easy access to data in a format that resembles a table.
For example, a 2D array with 3 rows and 4 columns might be written like this:
[ [10, 20, 30, 40],
[50, 60, 70, 80],
[90, 100, 110, 120] ]In this case:
The element 70 is at row index 1 and column index 2.
Arrays are typically zero-indexed, meaning the first element is at index 0.
This structure is ideal for representing systems where data naturally fits into rows and columns, such as spreadsheets or grids.
Higher-dimensional arrays
Practice Questions
FAQ
In some programming languages, especially those that use lists or arrays of arrays (like Python), it is possible to create what is known as a jagged array, where different rows in a 2D array have different lengths. This means the array is no longer a true rectangular grid, and attempting to access a column index that doesn’t exist in a particular row will raise an error such as an IndexError in Python. To handle this safely, it is important to check the length of each row before accessing its elements. For example, using conditional statements within loops to verify that an index exists can prevent crashes. Jagged arrays may occur unintentionally if data is appended incorrectly or imported unevenly from external sources. To enforce a uniform structure, the programmer can either validate the data before storage or explicitly initialise each row with the correct number of elements. Padding shorter rows with default values like 0 or None is also a common solution to preserve rectangular structure.
Sorting a 2D array requires specifying whether you're sorting rows individually, sorting by a specific column, or transforming the array before sorting. To sort individual rows, each row can be sorted using a built-in sort function. In Python, for instance, you can loop through each row and apply row.sort(). If sorting by a column — for example, arranging student records by their exam score in the second column — the array must be treated as a list of rows, and a custom sorting key must be defined. This involves using a function that extracts the desired column value for sorting. A common pitfall is forgetting that columns are not independently stored like rows in most languages, so column sorting usually involves restructuring or transposing the array temporarily. Another mistake is overwriting the original data unintentionally during sorting. To avoid data loss, it's good practice to copy the original array before applying transformations.
Yes, multi-dimensional arrays can be passed to functions or subroutines, and doing so allows for more modular and reusable code. When passing a 2D array to a function, it is important to ensure that the function has access to both dimensions — typically the number of rows and columns — especially in languages like C or Java, where array size information might not be automatically available. In Python, the array can be passed as a parameter like any other variable, and its structure remains intact. However, one must consider whether the function needs to modify the original array or just read from it. Arrays are usually passed by reference, meaning changes made within the function will affect the original array unless a copy is created. Clarity on whether the function mutates or preserves the data is critical, and naming conventions or documentation should reflect this. Also, when writing pseudocode in exams, use clear parameter definitions and describe the dimensions involved explicitly.
Searching for an element in a 2D array is usually done with a linear search, where each element is checked one by one using nested loops. This works well for small arrays or when the data is unsorted. However, linear search has a time complexity of O(n * m), where n is the number of rows and m is the number of columns, making it inefficient for very large arrays. If the array is sorted, more efficient methods like binary search may be applied — but only under certain conditions. For example, if each row is sorted individually and the entire array is treated as a flat list, a modified binary search can be used. Alternatively, if both rows and columns are sorted in increasing order, a staircase search algorithm can be used starting from the top-right or bottom-left corner, reducing complexity to O(n + m). Hashing may be used as a pre-processing step to enable faster lookups if key-value mappings are required, but this changes the structure and purpose of the data.
A shallow copy of a 2D array creates a new outer array, but the inner arrays (rows) are still references to the same memory locations as the original. This means that modifying a value in a row of the copied array will also change the corresponding value in the original array, since both arrays share the same inner lists. In contrast, a deep copy creates a completely independent copy of all elements, including all nested arrays, so changes made to the copied array do not affect the original. This distinction is especially important when passing arrays to functions or storing backups of data before manipulation. In Python, shallow copies are created with slicing or list() and deep copies can be made using list comprehensions or the copy.deepcopy() function. Failing to make a deep copy when needed can lead to unexpected behaviour and bugs, particularly in algorithms that rely on temporary states or rollback mechanisms.
