Двумерные массивы
Во многих задачах нужно работать не с одной строкой чисел, а с таблицей: оценки по предметам (класс × предмет), игровое поле, матрица чисел, карта с высотами.
Двумерный массив можно представлять как таблицу или сетку:
У такого массива есть элементы a[0][0], a[0][1], …, a[2][3].
Основное
Двумерный массив целых чисел:
int[][] a = new int[n][m]; // n строк, m столбцов
a[i][j] = 10; // записать значение в ячейку (i, j)
int x = a[i][j]; // прочитать значение
int rows = a.length; // количество строк
int cols = a[0].length; // количество столбцов в первой строке
Важно:
- индексы по строкам: от
0доa.length - 1; - индексы по столбцам: от
0доa[i].length - 1; - новый
int[][]по умолчанию заполнен нулями.
Идея двумерного массива
Один массив — это «линейка» значений:
Двумерный массив — это «таблица» или «поле»:
Можно думать о нём как об «массиве массивов»:
a[0]— первая строка (массивint[]);a[1]— вторая строка;a[i][j]— элемент в i‑й строке и j‑м столбце.
Объявление и создание двумерного массива
Общий шаблон:
Примеры:
int n = 3;
int m = 4;
int[][] a = new int[n][m]; // таблица n × m из целых
double[][] d = new double[5][5]; // 5 × 5 вещественных
boolean[][] used = new boolean[n][m]; // поле посещённых клеток
Можно создать и заполнить массив сразу литералами:
Чтение двумерного массива из ввода
Часто во входе сначала даны размеры n и m, затем n × m чисел.
import java.util.Scanner;
public class Read2DArrayExample {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(); // число строк
int m = in.nextInt(); // число столбцов
int[][] a = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = in.nextInt();
}
}
// вывод массива в виде таблицы
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
}
2 3 1 2 3 4 5 6
1 2 3 4 5 6
Здесь внешний цикл идёт по строкам (индекс i), внутренний — по столбцам (индекс j).
Сумма всех элементов
int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = in.nextInt();
}
}
int sum = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
sum = sum + a[i][j];
}
}
System.out.println(sum);
Суммы по строкам и столбцам
Суммы по строкам
int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = in.nextInt();
}
}
for (int i = 0; i < n; i++) {
int rowSum = 0;
for (int j = 0; j < m; j++) {
rowSum = rowSum + a[i][j];
}
System.out.println(rowSum);
}
Суммы по столбцам
int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = in.nextInt();
}
}
for (int j = 0; j < m; j++) {
int colSum = 0;
for (int i = 0; i < n; i++) {
colSum = colSum + a[i][j];
}
System.out.println(colSum);
}
Двумерный массив как игровое поле
Двумерный массив удобно использовать для представления игрового поля:
0 — пустая клетка, 1 — стена, 2 — персонаж и т.п.
int n = in.nextInt();
int m = in.nextInt();
int[][] field = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
field[i][j] = in.nextInt();
}
}
Пример проверки соседних клеток (аккуратно с границами):
int i = in.nextInt();
int j = in.nextInt();
// проверяем, есть ли клетка сверху
if (i > 0) {
int up = field[i - 1][j];
}
// снизу
if (i + 1 < n) {
int down = field[i + 1][j];
}
Что нужно запомнить
Двумерный массив можно представлять как таблицу n × m:
Первый индекс — номер строки, второй — номер столбца: a[i][j].
Размеры: a.length — количество строк, a[i].length — количество столбцов в строке i.
Типичный приём — вложенные циклы for по строкам и столбцам для чтения, обработки и вывода таблицы.
Заполнение двумерной таблицы
Под таблицей будем понимать набор из n × m элементов, структурированный в n строк и m столбцов. К каждому элементу обращаемся по номеру строки и столбца.
Например, таблица 5 × 6, заполненная числами от 0 до 29:
Значение элемента во второй строке и третьем столбце (индексация с нуля) равно 15.
Для работы с таблицами в C++ удобно использовать «вектор векторов»:
После этого получаем таблицу t из n строк и m столбцов, заполненную нулями.
Заполнение по порядку через отдельный счётчик:
То же можно сделать без переменной c:
Вывод таблицы:
Задача о заполнении таблицы змейкой
Нужно заполнить таблицу змейкой: строки с чётными индексами слева направо, строки с нечётными индексами справа налево.
Для 5 × 6 это выглядит так:
Решение:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<vector<int>> t(n, vector<int>(m));
int now = 0;
for (int i = 0; i < t.size(); ++i){ // число строк — t.size()
if (i % 2 == 0){
for (int j = 0; j < t[i].size(); ++j){ // число элементов в i-й строке — t[i].size()
t[i][j] = now;
++now;
}
} else {
for (int j = t[i].size() - 1; j >= 0; --j){
t[i][j] = now;
++now;
}
}
}
for (int i = 0; i < t.size(); ++i){
for (int j = 0; j < t[i].size(); ++j){
cout << t[i][j] << " ";
}
cout << endl;
}
return 0;
}
2 3
0 1 2 5 4 3
Работа с двумерной таблицей
Задача об обмене столбцов таблицы:
Дана таблица размера n × m. Нужно поменять местами столбцы с номерами p и q.
Решение:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, m, p, q;
cin >> n >> m >> p >> q;
vector<vector<int>> t(n, vector<int>(m));
for (int i = 0; i < t.size(); ++i){
for (int j = 0; j < t[i].size(); ++j){
cin >> t[i][j];
}
}
for (int i = 0; i < n; ++i){
swap(t[i][p], t[i][q]);
}
for (int i = 0; i < t.size(); ++i){
for (int j = 0; j < t[i].size(); ++j){
cout << t[i][j] << " ";
}
cout << endl;
}
return 0;
}
Задача о симметричной таблице:
Нужно проверить, симметрична ли квадратная таблица относительно главной диагонали.
Пример симметричной таблицы:
Решение:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<vector<int>> t(n, vector<int>(n));
for (int i = 0; i < t.size(); ++i){
for (int j = 0; j < t[i].size(); ++j){
cin >> t[i][j];
}
}
bool issym = true;
for (int i = 0; i < t.size(); ++i){
for (int j = 0; j < i; ++j){
if (t[i][j] != t[j][i]){
issym = false;
}
}
}
if (issym){
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
По материалам:
М. Густокашин. Введение в программирование на языке C++. Сириус Курсы. Перейти к курсу.
Двумерный массив – это список списков (таблица \(n \times m\)). Важно правильно создавать такую таблицу.
Основное
Если написать a = [[0] * m] * n, все строки будут ссылаться на один и тот же список, и изменения будут «размножаться» по всем строкам.
Чтение таблицы из ввода
n, m = map(int, input().split())
a = []
for _ in range(n):
row = list(map(int, input().split()))
a.append(row)
Вывод таблицы
В Java int[][] – это «массив массивов»: строки могут быть разной длины. В C++ и Python идея такая же: это тоже «таблица из строк», и строки тоже могут быть разной длины.
В Java новый int[][] сразу заполнен нулями. В C++ и Python это зависит от того, как создаёшь: если создать таблицу с начальными нулями – будут нули, если просто объявить и потом заполнять – значения появятся только после ввода.
В Java размеры удобно брать через a.length и a[i].length. В C++ – через a.size() и a[i].size(). В Python – через len(a) и len(a[i]).
Ошибка выхода за границы в Java и C++ обычно приводит к аварийному завершению (или странному поведению в C++). В Python при неверном индексе будет IndexError.
В Python важно правильно создавать таблицу, чтобы строки были независимыми: [[0] * m for _ in range(n)].