Прошло много времени с тех пор, как я обсуждал какие-либо вопросы о кодировании или алгоритме , поэтому я решил вернуться к одной из самых популярных проблем кодирования на основе массива — найти пропущенные числа в данном массиве . Возможно, вы уже слышали или видели эту проблему на своем собеседовании по программированию, но существует множество различных версий повышения уровня сложности, которые интервьюер обычно использует, чтобы запутать кандидата и дополнительно проверить его способность адаптироваться к частым изменениям. В прошлом я демонстрировал, как найти отсутствующее число в отсортированном массиве, а также в несортированном целочисленном массиве в Java, используя BitSet (см. Здесь ), но только с одним отсутствующим числом и без дубликатов.
Это несколько облегчает проблему, но что вы будете делать, если интервьюер скажет вам, что массив содержит дубликаты и более одного числа отсутствуют? Ну, это то, что мы обсудим в этой статье, но перед этим давайте правильно сформулируем задачу.
1. Постановка проблемы:
Вы дали массив целых чисел размера N. Массив содержит числа от 1 до N-1, но в массиве, который также содержит дубликаты, отсутствует пара чисел. Напишите Java-программу для печати отсутствующего числа из последовательности.
Например, если данный массив
{1, 1, 2, 3, 5, 5, 7, 9, 9, 9}, то имеет длину
10 и содержит числа от 1 до 9. В этом случае пропущенными числами являются 4, 6 и 8.
2. Решение:
Когда вы видите, что вопрос заключается в том, чтобы найти пропущенное число в массиве , вы можете подумать о нашем более раннем решении вычисления суммы всех чисел и вычитания ее из ожидаемой суммы, чтобы найти пропущенное число, но, к сожалению, в этой ситуации это не сработает, потому что чем один номер отсутствует, а также содержит дубликаты.
В этом случае нам нужно использовать другой подход, что-то вроде переклички, которую вы бы видели в своей школе.
У учителя есть регистр с именами всех учеников, он просматривает список и помечает пропуски красным цветом. Мы можем использовать тот же подход, чтобы найти все пропущенные числа в списке.
Мы можем использовать массив в качестве регистра и его индекс в качестве имен чисел. Мы перебираем данный массив и помечаем галочкой все имеющиеся числа, сохраняя один из их соответствующих индексов. Например, если первое число в данном массиве равно 5 (поскольку массив не отсортирован), то мы сохраняем 1 в индексе 5, например, register[5] = 1
После того, как мы пройдем все заданные числа, мы можем пройти через наш массив регистров и распечатать все индексы, где значение равно нулю. Это отсутствующие или отсутствующие номера.
Это решение также защищено от дубликатов, потому что если число приходит один или два раза, мы просто сохраняем 1 в соответствующем индексе.
3. Код:
Теперь, когда мы знаем, как решить эту проблему пропущенных чисел в несортированном целочисленном массиве с дубликатами, пришло время превратить это решение в код и работающую Java-программу.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/* * Java Program to find missing numbers in an integer * array with duplicates. Array may contains more * than one duplicates. * * input: {1, 1, 2, 3, 5, 5, 7, 9, 9, 9}; * output: 4, 6, 8 */ public class Hello { public static void main(String[] args) { // given input int [] input = { 1 , 1 , 2 , 3 , 5 , 5 , 7 , 9 , 9 , 9 }; // let's create another array with same length // by default all index will contain zero // default value for int variable int [] register = new int [input.length]; // now let's iterate over given array to // mark all present numbers in our register // array for ( int i : input) { register[i] = 1 ; } // now, let's print all the absentees System.out.println( "missing numbers in given array" ); for ( int i = 1 ; i < register.length; i++) { if (register[i] == 0 ) { System.out.println(i); } } } } |
1
2
3
4
5
|
Output missing numbers in given array 4 6 8 |
Это самая простая Java-программа для решения этой проблемы. Вы можете видеть, что мы жестко закодировали массив ввода, но вы также можете изменить программу для получения ввода от пользователя, используя класс Scanner, как показано в этом примере .
Код точно такой же, как и решение, мы создали другой массив, скопировав длину из исходного массива и использовав его, чтобы пометить числа, которые есть.
Поскольку индексы массива также целочисленные и находятся в диапазоне входных значений, мы можем использовать их для использования как в качестве данных, так и метаданных. Если бы массив содержал число, которое не находится в диапазоне от 1 до N-1, то мы не могли бы использовать массив.
Вот краткое описание алгоритма и кода на слайде для лучшего понимания:
4. Анализ
Теперь настало время проанализировать наше решение, чтобы определить сложность ЦП и памяти с помощью обозначения Big O. Если вы посмотрите на код, то обнаружите, что мы создаем другой массив с тем же размером, что означает, что он имеет сложность памяти или пространства O (n) .
Это означает, что если массив слишком большой, то есть содержит все числа в целочисленном диапазоне, то у нас будет гораздо больше памяти, которая может быть недоступна, и наша программа может выбросить OutOfMemoryError в Java . Это еще более возможно, потому что массиву требуется непрерывный кусок памяти.
Итак, если мы сможем удалить дополнительный массив, который на самом деле ничего не содержит, и найдем способ просто сохранить пропущенное число, которое намного меньше всего числа, которое мы можем улучшить в этом решении, то, что вы, ребята, должны подумать.
Для усложнения времени вы можете видеть, что мы перебираем весь массив, чтобы пометить все имеющиеся числа, а затем снова переходим к другому массиву такой же длины, чтобы найти пропуски. Это означает, что временная сложность этого решения составляет O (n) + O (n) или O (2N), которая в большой записи O все еще O (n) .
Мы можем еще больше улучшить это решение, если найдем способ печатать открепления при выполнении итерации по данному массиву . Опять же, что-то думать о вас, ребята.
Вот и все об этой классической проблеме поиска пропущенных чисел в данном целочисленном массиве . В этой части мы нашли решение для поиска нескольких пропущенных чисел в несортированном массиве с дубликатами. Пространственно-временная сложность нашего решения O (n).
См. Оригинальную статью здесь: Как найти K пропущенных чисел в массиве целых чисел с дубликатами в Java?
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |