Задачи на массивы - прагматичный подход
Данный текст опубликован в рамках подготовки к экзамену учеников Компьютерной школы мехмата ЮФУ (sunschool.mmcs.sfedu.ru) по курсу "Программирование 2 ступень".
Во всех задачах на массивы требуется уметь описывать массивы, вводить их, заполнять случайными числами, выводить. Очень часто требуется цикл по массиву с перебором всех элементов.
Описание массива и выделение памяти
var a: array of integer := new integer[10];
Если в задаче требуется создать массив из N элементов, то N надо предварительно ввести:
var N := ReadInteger;
var a := new integer[N];
for var i:=1 to a.Length-1 do
Print(a[i])
foreach var x in a do
Print(x)
В случае foreach невозможно изменение элементов.
Ввод массива с клавиатуры
var N := ReadInteger;
var a := new integer[N];
for var i:=1 to a.Length-1 do
a[i] := ReadInteger;
var N := ReadInteger;
var a := ReadArrInteger(N);
Вывод массива
Поиск в массиве элементов и их индексов
Для проверки, есть ли элемент в массиве, используется операция in:
Найти индекс первого элемента, равного чему то:
var ind := a.IndexOf(3); // индекс первой 3 или -1 если не найдено
Найти индекс первого элемента, удовлетворяющего условию:
var ind := a.FindIndex(x -> x mod 2 = 0); // индекс первого четного или -1 если не найдено
FindIndex можно также использовать для проверки, есть ли элементы, удовлетворяющие условию:
var Has := a.FindIndex(x -> x in 3..5) <> -1; // есть ли элементы от 3 до 5
Генерация массива по заданному правилу
var a := ArrFill(N,1); // заполнить N элементов значением 1
Для заполнения каждого элемента по правилу a[i] := i + 1 пользуемся функцией ArrGen:
var a := new integer[N];
for var i:=1 to a.Length-1 do
a[i] := i + 1;
Для заполнения массива, в котором задан первый элемент, а каждый следующий определяется по предыдущему, пользуемся
var a := ArrGen(N, 1, x -> следующий);
Здесь N - количество элементов, 1 – первый элемент.
Например, если каждый следующий больше предыдущего на 2:
var a := ArrGen(N, 1, x -> x + 2);
Если же каждый следующий больше предыдущего в 2 раза:
var a := ArrGen(N, 1, x -> x * 2);
Преобразование элементов по заданному правилу
Будем считать массив a заданным (например, введенным с клавиатуры).
Чтобы увеличить все элементы массива на 1, пользуемся методом-процедурой Transform:
Иногда удобно преобразовывать элементы массива, используя цепочку методов. В этом случае следует использовать метод Select. Возможно потребуется преобразование назад к массиву, тогда используем дополнительно метод ToArray:
a := a.Select(x -> x + 1).ToArray;
Если некоторые элементы надо преобразовать по одному правилу, а остальные – по другому или не преобразовывать вовсе, то лучше воспользоваться циклом. Например, для обнуления нечетных:
for var i:=1 to a.Length-1 do
if a[i] mod 2 <> 0 then
a[i] := 0;
Если нечетные надо уменьшить на 1, а четные увеличить на 1:
for var i:=1 to a.Length-1 do
if a[i] mod 2 <> 0 then
a[i] -= 1
else a[i] += 1;
Немного менее понятным будет код с Transform и использованием условной операции:
a.Transform(x -> x mod 2 = 0 ? x - 1 : x + 1);
Фильтрация элементов по условию
Если в массиве надо отобрать элементы, удовлетворяющие определенному условию, это называется фильтрацией. Фильтрацию проще всего выполнять с помощью метода Where. Например, если требуется отфильтровать и вывести элементы массива, меньшие 5, то вот код:
Если надо отфильтровать данные и записать результат в тот же массив, то используем преобразование к массиву методом ToArray:
a := a.Where(x -> x < 5).ToArray;
Бывает так, что после фильтрации надо вычислить какую-то характеристику отфильтрованных элементов – например, найти их сумму, среднее или минимум-максимум:
a.Where(x -> x > 10).Sum.Print;
a.Where(x -> x in 2..8).Average.Print;
a.Where(x -> x mod 2 = 0).Min.Print;
можно вычислять количество элементов, удовлетворяющих некоторому условию. Однако то же можно сделать с помощью метода Count с параметром (см. следующий пункт).
Кроме того, отфильтрованные элементы можно далее преобразовывать методом Select, используя цепочку методов:
a.Where(x -> x in 2..8).Select(x -> x + 10).Println;
Задачи на поиск количества элементов, удовлетворяющих некоторому условию
Если надо найти количество опеределенных элементов, то используется метод CountOf:
a.CountOf(3) – количество троек в массиве
Если же надо найти количество элементов, удовлетворяющих условию, то используется метод Count с параметром:
Задачи на использование срезов
Срез массива – это набор элементов массива, расположенных последовательно или с некоторым шагом.
Если есть массив из 10 элементов
то a[1:5]
– это срез элементов массива с индексами от 1 до 4
В срезах можно пропускать первый или последний индекс:
a[5:]
– срез с элемента с индексом 5 до конца
Кроме этого, есть срезы с шагом:
a[::2]
– все элементы с четными индексами
a[1::2]
– все элементы с нечетными индексами
a[::-1]
– инвертированный массив (все элементы в обратном порядке)
У срезов можно вычислять различные характеристики, например, сумму элементов, среднее или максимальный:
a[::2].Sum
– сумма элементов с четными индексами
a[1::2].Average
– среднее элементов с нечетными индексами
a[:5].Min
– минимальный среди первых 5 элементов
Можно комбинировать срезы и методы массивов:
a[:5].Where(x -> x mod 2 = 0)
– отфильтровать четные элементы среди первых пяти элементов массива
Индексация с конца и срезы
В ряде задач может встречаться индексация элементов с конца:
a[^1]
– это первый элемент с конца (последний)
a[^2]
– это второй элемент с конца (предпоследний)
Индексация с конца может сочетаться со срезами, например,
a[:^1]
– все элементы кроме последнего
a[^2:]
– два последних элемента массива
a[1:^1].Sum
– сумма всех элементов кроме нулевого и последнего