Какое число не содержится в массиве

Какое число не содержится в массиве thumbnail

Задача: в массиве длиной N найти элемент, который повторяется больше N/2 раз.

Казалось бы, чего тут думать? Возьмём Dictionary<значение элемента, число появлений>, за один проход по массиву сосчитаем появления каждого элемента, потом выберем из словаря искомый элемент. Решение за O(N), куда может быть ещё быстрее?

Есть один нюанс: для словаря нам потребуется O(N) дополнительной памяти — в несколько раз больше размера исходного массива, и это при реализации словаря хоть хэш-таблицей, хоть деревом. Что будем делать, если наша цель — обработка сигнала неким устройством с маленькой памятью? Массив — замеры уровня сигнала, из которых один — «настоящий» передаваемый уровень, а остальные — шум и помехи. Неужели придётся для определения «настоящего» уровня возиться с хэш-таблицами и деревьями?

К счастью, нет: достаточно O(1) дополнительной памяти, и по-прежнему одного прохода по массиву. Алгоритм Бойера-Мура — тех самых Бойера и Мура, что придумали намного более известный алгоритм поиска подстроки — проще всего представить следующим образом: на вечеринке собрались N людей, и на каждом по одному элементу из массива. Когда встречаются двое, у которых элементы разные, они присаживаются это обсудить. В конце концов останутся стоять только люди с одинаковыми элементами; очевидно, это тот самый элемент, который встречался больше N/2 раз.

Реализация алгоритма Бойера-Мура занимает всего несколько строк:

int* majority(int[] array, int N) {
int confidence = 0; // количество людей, не нашедших пары и оставшихся стоять
int* candidate = NULL; // последний человек, не нашедший пару —
// возможно, его элемент встречается чаще всего

// проходим по массиву и усаживаем пары с разными элементами
for (int i = 0; i<N; i++) {

// если до сих пор все сидят, то следующему пока придётся постоять
if (confidence == 0) {
candidate = array+i;
confidence++;
}

// иначе следующий либо садится с одним из стоящих,
// либо будет стоять вместе с ними, если у него такой же элемент
else if (*candidate == array[i]))
confidence++;
else
confidence—;
}

return confidence > 0 ? candidate : NULL;
}

В конце мы получаем «наиболее вероятного кандидата» на присутствие в N/2 экземплярах: если такой элемент в массиве действительно существует, то он будет найден; если же такого элемента нет, то возможно, стоять останется просто какой-то бедолага, которому не хватило пары. Для более строгой реализации majority требуется пройти по массиву второй раз и проверить, действительно ли найденный элемент встречается требуемое количество раз.

Усложним задачу. Теперь в массиве длиной N надо найти элементы, которые повторяются больше N/3 раз — если есть два, то оба, если есть один, то один.

Например, нашему устройству с маленькой памятью нужно принять двоичный сигнал с неизвестными уровнями нуля и единицы, но известно, что примерно половину времени передаётся ноль, примерно половину времени — единица, а любые отличные от них уровни сигнала — это помехи и дребезг от переключения.

Идею прошлого алгоритма несложно обобщить и для троек: пусть люди с разными элементами рассаживаются по трое. Значит, в конце вечеринки останутся стоять люди максимум с двумя разными элементами. Если какой-то элемент встречался больше N/3 раз, значит человек с ним гарантированно останется стоять, ведь сидящих троек получится не больше N/3. Как и в прошлом случае, если искомые элементы существуют — то они будут найдены, но если их нет — то найтись может кто попало.

Код мало отличается от предыдущего: по-прежнему один проход по массиву и O(1) дополнительной памяти.

void majority(int[] array, int N, int** cand1, int** cand2) {
int conf1 = 0, conf2 = 0; // количество стоящих людей с двумя элементами
*cand1 = NULL; *cand2 = NULL; // два стоящих человека с разными элементами

// проходим по массиву и усаживаем тройки с разными элементами
for (int i = 0; i<N; i++) {

// у следующего такой же элемент, как у стоящих? тогда встанет вместе с ними
if (conf1 > 0 && **cand1 == array[i])
conf1++;
else if (conf2 > 0 && **cand2 == array[i])
conf2++;
else // может, стоят только с одним элементом, или вообще стоящих нет?
if (conf1 == 0) {
*cand1 = array+i;
conf1++;
} else if (conf2 == 0) {
*cand2 = array+i;
conf2++;
}
else { // стоят с двумя другими элементами, так что усаживаем всю тройку
conf1—;
conf2—;
}
}

if(conf1 == 0) *cand1 = NULL;
if(conf2 == 0) *cand2 = NULL;
}

Читайте также:  В каких содержится медь

Этот алгоритм опубликован в 1982 американскими учёными Джаядевом Мисрой и Дэвидом Грисом (Jayadev Misra & David Gries), и в их работе используется более скучная метафора — мешок с N числами, из которого они извлекают по 3 разных числа за каждую операцию. Кроме того, их псевдокод не похож ни на один понятный современному программисту язык. Мне больше понравилось объяснение их алгоритма в позапрошлогоднем конспекте лекций американского профессора Амита Чакрабарти.

В наиболее общей форме, когда в массиве длиной N надо найти элементы, которые повторяются больше N/k раз — придётся-таки воспользоваться словарём. Хранить в словаре мы будем только те элементы, с которыми люди стоят — т.е. не больше k-1 записей.

int[] majority(int[] array, int N, int k) {
// словарь стоящих людей изначально пуст
Dictionary<int,uint> candidates = new Dictionary<int,uint>{};

// проходим по массиву и усаживаем группы по k
for (int i = 0; i<N; i++) {

// у следующего такой же элемент, как у стоящих? тогда встанет вместе с ними
if (candidates.ContainsKey(array[i]))
candidates[array[i]]++;
else // может, стоят менее чем с k-1 элементами?
if (candidates.Count < k — 1)
candidates[array[i]] = 1;
else // стоят с k-1 другими элементами, так что усаживаем всю группу
foreach(int l in candidates.Keys)
if (candidates[l]— == 0) // (**)
candidates.Remove(l); // (*)
}

return candidates.Keys.ToArray();
}

В этой наиболее общей форме алгоритма — по-прежнему один проход по массиву и O(k) дополнительной памяти. Если мы пользуемся для реализации словаря хэш-таблицей, а все записи в словаре свяжем в список — тогда общая сложность алгоритма останется линейной: строчка (*) с удалением записи из словаря выполняется самое большее N раз, ведь на каждой итерации основного цикла в словарь добавляется не больше одной записи. Читателям в качестве упражнения предлагается понять, почему строчка (**) не нарушает линейности алгоритма.

Таким образом наше устройство с маленькой памятью смогло бы общаться с одним пушистым зверьком, недавно препарированным хабраумельцами. Сигналы этого зверька имеют пять логических уровней: полагаем k=6, и получаем все пять уровней прямо на ходу, даже без сохранения сигнала в память. Нужно только обеспечить протоколом, чтобы все пять уровней встречались в сигнале одинаково часто.

Для алгоритма Мисры-Гриса упоминаются и другие применения. Например, можно следить в реальном времени за трафиком в сети, и если некий один хост потребляет непропорционально большую часть трафика — начинать расследование. Так же можно следить за кликами по баннерам, за финансовыми транзакциями, за потоком инструкций в моделируемом процессоре… В общем, всюду, где большое число повторений — подозрительная аномалия.

За оживление текста иллюстрациями надо благодарить Nitatunarabe

Источник

pascalУсловие задачи : Массив задан датчиком случайных чисел на интервале [-37, 66]. Найти наименьший нечетный элемент. Размер произвольный. (Язык Pascal)

Сложность: легкая.

Для начала продумаем наше решение. Ну само собой сначала заполним массив случайными числами с помощью цикла, затем с помощью другого цикла найдем наименьший нечетный элемент.

Для того чтобы решить задачу нам понадобятся следующие переменные:

1. Переменная mass — для массива
2. Переменная i — для цикла for
3. Переменная min — для минимального нечетного элемента
4. Переменная count — для кол-ва элементов массива

Начнем мы с каркаса нашей программы :

type
massiv = array [1..100] of integer; // создаём свой тип данных для массива

var
mass : massiv; // объявляем
i, min, count : integer; // переменные
begin
randomize; // включаем генератор случайных чисел

write(‘Введите размер массива : ‘);readln(count); // вводим размер массива

end.

Тут мы создали свой тип данных для массива, как и зачем читайте ( тут ) включили генератор случайных чисел , подробнее (тут), ну и попросили пользователя ввести кол-во элементов массива.

Теперь давайте заполним наш массив случайными числами с помощью цикла for и выведем все его элементы, цикл должно у нас быть от 1 до количества элементов, чтобы заполнить весь массив, пишем:

for i:=1 to count do // пускаем цикл для заполнения массива
begin
mass[i] := random(104) — 37; // присваиваем случайное число
write(mass[i], ‘ | ‘); // выводим число
end;

Для того чтобы найти минимальный элемент делается следующее, для начала задаётся начальное значение переменной min, обычно это первое значение массива, дальше оно уже сравнивается со всеми остальными элементами массива и если какое-то меньше min, то уже оно становится минимальным, но также надо не забыть проверить на нечетность.

Читайте также:  Янтарная кислота в каких продуктах содержится больше всего

min := mass[1]; // за минимальный элемент берем 1-е число, чтобы было с чем сравнивать

for i:=2 to count do // ищем минимальный элемент
if (mass[i] < min) AND (mass[i] mod 2 <> 0) then // проверяем его на условие, если прошло условие
min := mass[i]; // присваиваем новое значение

i = 2 , потому что первый элемент у нас уже известен min := mass[1] смысла сравнивать первый элемент с первым нету.

После этого цикла у нас должен быть найден наименьший нечетный элемент, но может быть такая ситуация что начальное значение переменной min и есть наименьший элемент, т.е. все остальные элементы больше начального значения, в этом случаи нам надо проверить и его на нечетность:

if ( min mod 2 <> 0) then // если вдруг минимальным остался самый первый элемент, то надо его тоже проверить на четность
writeln(‘Минимальный элемент равен : ‘, min)
else
writeln(‘В массиве нет нечетных элементов!’);

Т.е. если последнее число которое содержится в переменной min нечетное то мы его и выводим, иначе говорим что в массиве нет нечетных элементов.

Всё решение задачи Pascal :

type
massiv = array [1..100] of integer; // создаём свой тип данных для массива

var
mass : massiv; // объявляем
i, min, count : integer; // переменные
begin
randomize; // включаем генератор случайных чисел

write(‘Введите размер массива : ‘);readln(count); // вводим размер массива

for i:=1 to count do // пускаем цикл для заполнения массива
begin
mass[i] := random(104) — 37; // присваиваем случаное число
write(mass[i], ‘ | ‘); // выводим число
end;

min := mass[1]; // за минимальный элемент берем 1-е число, чтобы было с чем сравнивать

for i:=2 to count do // ищем минимальный элемент
if (mass[i] < min) AND (mass[i] mod 2 <> 0) then // проверяем его на условие, если прошло условие
min := mass[i]; // присваиваем новое значение

writeln; // для красоты переносим строку

if ( min mod 2 <> 0) then // если вдруг минимальным остался самый первый элемент, то надо его тоже проверить на четность
writeln(‘Минимальный элемент равен : ‘, min)
else
writeln(‘В массиве нет нечетных элементов!’);

readln; // чтобы программа не закрывалась
end.

Вот результат :

zadachi-po-pascal-najti-naimenshij-nechetnyj-element-massiva

Источник

array7-17

Приветствуем читателей нашего сайта! Сегодня мы с вами решим задачи Array7-17.

Array7-17. (Одномерные массивы: вывод элементов)

Array7°. Дан массив размера N. Вывести его элементы в обратном порядке.

Не забываем про то, что циклом for можно пробегать числа не только от меньших к большим, но от больших к меньшим.

program array7;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Элементы в обратном порядке: ‘);
for i := N downto 1 do write(arr[i], ‘ ‘)
end.

Array8. Дан целочисленный массив размера N. Вывести все содержащиеся в данном массиве нечетные числа в порядке возрастания их индексов, а также их количество K.

program array8;

var
arr: array[1..10] of integer;
N, i, k: integer;

begin
k := 0; {счётчик}
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Нечетные элементы массива: ‘);
for i := 1 to N do
if arr[i] mod 2 <> 0 then
begin
write(arr[i], ‘ ‘);
inc(k);
end;
writeln;
write(‘Количество нечетных элементов массива: ‘, k);
end.

Array9. Дан целочисленный массив размера N. Вывести все содержащиеся в данном массиве четные числа в порядке убывания их индексов, а также их количество K.

program array9;

var
arr: array[1..10] of integer;
N, i, k: integer;

begin
k := 0; {счётчик}
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Четные элементы массива: ‘);
for i := N downto 1 do
if arr[i] mod 2 = 0 then
begin
write(arr[i], ‘ ‘);
inc(k);
end;
writeln;
write(‘Количество четных элементов массива: ‘, k);
end.

Array10. Дан целочисленный массив размера N. Вывести вначале все содержащиеся в данном массиве четные числа в порядке возрастания их индексов, а затем — все нечетные числа в порядке убывания их индексов.

program array10;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Четные элементы массива: ‘);
for i := 1 to N do
if arr[i] mod 2 = 0 then
write(arr[i], ‘ ‘);
writeln;
write(‘Нечетные элементы массива: ‘);
for i := N downto 1 do
if arr[i] mod 2 <> 0 then
write(arr[i], ‘ ‘);
end.

Читайте также:  В каких продуктах содержится мало железа

Array11. Дан массив A размера N и целое число K (1 ≤ K ≤ N). Вывести элементы массива с порядковыми номерами, кратными K: AK, A2·K, A3·K, …. Условный оператор не использовать.

program array11;

var
arr: array[1..10] of integer;
N, K, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Введите K: ‘);
readln(K);
i := 1;
write(‘Выбранные элементы массива: ‘);
repeat
write(arr[K * i],’ ‘);
inc(i)
until K * i > N;
end.

Array12. Дан массив A размера N (N — четное число). Вывести его элементы с четными номерами в порядке возрастания номеров: A2, A4, A6, …, AN. Условный оператор не использовать.

program array12;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N(чётное): ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Выбранные элементы массива: ‘);
i := 2;
repeat
write(arr[i],’ ‘);
inc(i, 2)
until i > N;
end.

Array13. Дан массив A размера N (N — нечетное число). Вывести его элементы с нечетными номерами в порядке убывания номеров: AN, AN−2, AN−4, …, A1. Условный оператор не использовать.

program array13;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N(нечётное): ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Выбранные элементы массива: ‘);
repeat
write(arr[N],’ ‘);
N := N — 2;
until N < 1;
end.

Array14. Дан массив A размера N. Вывести вначале его элементы с четными номерами (в порядке возрастания номеров), а затем — элементы с нечетными номерами (также в порядке возрастания номеров):
A2, A4, A6, …, A1, A3, A5, ….
Условный оператор не использовать.

program array14;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Элементы массива: ‘);
i := 2;
repeat
write(arr[i],’ ‘);
i := i + 2;
until N < i;
i := 1;
repeat
write(arr[i],’ ‘);
i := i + 2;
until N < i;
end.

Array15. Дан массив A размера N. Вывести вначале его элементы с нечетными номерами в порядке возрастания номеров, а затем — элементы с четными номерами в порядке убывания номеров:
A1, A3, A5, …, A6, A4, A2.
Условный оператор не использовать.

program array15;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Элементы массива: ‘);
i := 1;
repeat
write(arr[i],’ ‘);
i := i + 2;
until N < i;
N := N div 2; {Количество чётных элементов}
repeat
write(arr[N * 2],’ ‘);
N := N — 1;
until N = 0;
end.

Array16°.  Дан массив A размера N. Вывести его элементы в следующем порядке:
A1, AN, A2, AN−1, A3, AN−2, ….

program array16;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N); {Например, 5}
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]); {например, 1 2 3 4 5}
write(‘Элементы массива: ‘);
for i := 1 to N div 2 do {5 div 2 = 2}
begin
write(arr[i],’ ‘);
write(arr[N — i + 1],’ ‘)
end;
{программа выведет в 1 цикл — 1 5, а во 2 цикл — 2 4}
{Если N — нечётное, то необходимо вывести оставшийся
элемент (3 в данном случае),
который расположен сразу за средним элементом}
if N mod 2 = 1 then write(arr[N div 2 + 1]);
end.

Array17.  Дан массив A размера N. Вывести его элементы в следующем порядке:
A1, A2, AN, AN−1, A3, A4, AN−2, AN−3, ….

program array17;

var
arr: array[1..10] of integer;
N, i: integer;

begin
write(‘Введите N: ‘);
readln(N);
write(‘Введите элементы массива: ‘);
for i := 1 to N do
read(arr[i]);
write(‘Элементы массива: ‘);
for i := 1 to N div 4 do
{N div 4 показывает нам, сколько четверок
содержится в данном массиве}
write(arr[2*i — 1],’ ‘, arr[2*i],’ ‘, arr[N + 2 — 2 * i],’ ‘, arr[N + 1 — 2 * i],’ ‘);
{Рассматриваем три оставшихся случая:}
if N mod 4 > 0 then write(arr[2 * (N div 4) + 1],’ ‘);
if N mod 4 > 1 then write(arr[2 * (N div 4) + 2],’ ‘);
if N mod 4 > 2 then write(arr[N — 2 * (N div 4)])
end.

На сегодня всё! Если у вас возникли вопросы, задавайте их в комментариях. И не забывайте рассказывать о нашем сайте своим друзьям!

Источник