#java
Вопрос:
Меня попросили написать код, который указывает, есть ли в целочисленном массиве повторяющиеся элементы или нет. Это то, что у меня есть до сих пор:
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; for (int i = 0; i lt; input.length; i ) { for (int j = i 1; j lt; input.length; j ) { if (input[i] != input[j]) { hasDuplicates = false; } else if (input[i] == input[j]) { hasDuplicates = true; } } }
Однако этот код работает не так, как предполагалось, потому hasDuplicates
что он всегда false
работает .
Комментарии:
1. потому что вы должны вернуться, как только определите, что в списке есть дубликаты. вы, по сути, перезаписываете свои предыдущие результаты на каждой итерации
2. Если вы проследите шаги в своем коде вручную, вы увидите, где вы ошиблись.
Ответ №1:
Как только вы решите , что массив hasDuplicates
, вы никогда не сможете его изменить; вы не сможете заставить исчезнуть дубликат после. Также используйте break
цикл, в данный момент hasDuplicates
становится правдой
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; for (int i = 0; i lt; input.length; i ) { for (int j = i 1; j lt; input.length; j ) { if (input[i] == input[j]) { hasDuplicates = true; break; } } if (hasDuplicates) break; }
Еще проще в методе, непосредственно использовать return
static boolean hasDup(int[] input) { for (int i = 0; i lt; input.length; i ) for (int j = i 1; j lt; input.length; j ) if (input[i] == input[j]) return true; return false; }
Ответ №2:
Вы также можете выполнить итерацию по массиву один раз, если используете хэш-набор. Если add() возвращает false, то мы знаем, что видели это число раньше.
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; HashSetlt;Integergt; duplicateSet = new HashSetlt;gt;(); for (int i = 0; i lt; input.length; i ) { if(!duplicateSet.add(Integer.valueOf(input[i]))) { hasDuplicates = true; break; } } return hasDuplicates;
Комментарии:
1.
new Integer()
может создать ненужные накладные расходы. ИспользуйтеInteger.valueOf()
вместо этого или, еще лучше, автобоксы.
Ответ №3:
Вы также можете воспользоваться преимуществами заданной структуры данных:
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; Setlt;Integergt; set = new HashSetlt;gt;(input.length); for (int i : input) { if (set.add(i)) { hasDuplicates = false; } else { hasDuplicates = true; break; } }
add(E e) Set возвращает значение true, если этот набор еще не содержал указанный элемент.
Вкратце:
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; Setlt;Integergt; set = new HashSetlt;gt;(input.length); for (int i : input) { if (!set.add(i)) { hasDuplicates = true; break; } }
Ответ №4:
Java 8 облегчает жизнь. вот, пожалуйста
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = false; if(Arrays.stream(input).distinct().count() != input.length) hasDuplicates=true; System.out.println(hasDuplicates);
Комментарии:
1. Это красиво, лаконично и читабельно. Однако, если входные данные содержат миллион элементов, а первые два являются дубликатами, другие ответы немедленно вернут значение true. Ваш по-прежнему будет просматривать оставшиеся 999 998 элементов, прежде чем вернется значение true.
Ответ №5:
Используя потоки Java 8, останавливаясь на первом найденном дубликате, однострочном:
int[] input = {1, 2, 3, 4, 1}; boolean hasDuplicates = !(Arrays.stream(input).allMatch(new HashSetlt;gt;()::add))