Как найти единственное число в массиве, которое не встречается дважды [дубликат]
этот вопрос уже есть ответ здесь:
следующее взято из собеседования:
в заданном массиве, содержащем целые числа, каждое число повторяется один раз, за исключением одного, который не повторить. Написать функцию что находит число, которое не повторяется.
Я думал об использовании HashSet, но это может все усложнить...
есть идеи простого решения?
5 ответов:
вы можете определить целое число" результат", инициализированное до 0, а затем выполнить некоторые побитовые операции, применив логику XOR ко всем элементам в вашем массиве.
в конце "результат" будет равен единственному элементу, который появляется только один раз.
result = 0 for i in array: result ^= i return result
http://en.wikipedia.org/wiki/Bitwise_operation#XOR
например, если Ваш массив содержит элементы [3, 4, 5, 3, 4], алгоритм возврата
3 ^ 4 ^ 5 ^ 3 ^ 4
но оператор XOR ^ ассоциативен и коммутативен, поэтому результат также будет равен:
(3 ^ 3) ^ (4 ^ 4) ^ 5
Так как i ^ i = 0 для любого целого числа i, и i ^ 0 = i, у вас есть
(3 ^ 3) ^ (4 ^ 4) ^ 5 = 0 ^ 0 ^ 5 = 5
Я видел этот вопрос раньше. Это трюк. Предполагая, что все повторяющиеся числа появляются ровно дважды, вы делаете это:
int result = 0; for (int a : arr) result ^= a;
еще одно "обычное" решение (на Java):
public static int findSingle(int[] array) { Set<Integer> set = new HashSet<Integer>(); for (int item : array) { if (!set.remove(item)) { set.add(item); } } assert set.size() == 1; return set.iterator().next(); }
на мой взгляд, решение с XOR является своего рода красивым.
Это не так быстро, как XOR, но использование HashSet делает его близким к O(n). И это, конечно, более читабельно.
лучший ответ уже дан (XOR-ing элементы), это обеспечить альтернативный, более общий способ.
если входной массив будет отсортирован (мы можем сделать его отсортированным), мы могли бы просто перебирать элементы попарно (шагая на 2) , и если элементы "пары" разные, мы сделали:
public static int findSingle(int[] arr) { Arrays.sort(arr); for (int i = 0, max = arr.length - 1; i < max; i += 2) if (arr[i] != arr[i + 1]) return arr[i]; return arr[arr.length - 1]; // Single element is the last }
Примечание: это решение сортирует входной массив; если это нежелательно или не разрешено, его можно клонировать первый:
arr = arr.clone();
если входной массив отсортирован, то
Arrays.sort(arr)
вызов можно оставить, конечно.обобщение
преимущество этого решения заключается в том, что оно может быть применено ко всем типам, которые сопоставимы и поэтому могут быть отсортированы (типы, которые реализуют
Comparable
), напримерString
илиDate
. ЭлементXOR
решение ограничено только числами.вот немного измененный версия, которая принимает входной массив любого типа элемента, который сопоставим:
public static <E extends Comparable<E>> E findSingle(E[] arr) { Arrays.sort(arr); for (int i = 0, max = arr.length - 1; i < max; i += 2) if (arr[i].compareTo(arr[i + 1]) != 0) return arr[i]; return arr[arr.length - 1]; // Single element is the last }
Примечание: В большинстве случаев вы также можете использовать
arr[i].equals(arr[i + 1])
для сравнения элементов вместо использованияComparable.compareTo()
. Дополнительные сведения см. В связанной документации. Цитируя соответствующую часть:настоятельно рекомендуется, но не строго требовал, чтобы
(x.compareTo(y)==0) == (x.equals(y))
. Вообще говоря, любой класс, который реализуетComparable
интерфейс и нарушение этого условия должно четко указывать на данный факт. Рекомендуемый язык " Примечание: этот класс имеет естественный порядок, который не соответствует equals."теперь вы можете называть это
String[]
например:System.out.println(findSingle(new String[] { "1", "2", "3", "1", "3" }));
выход:
2
конечные ноты:
начиная с постановки задачи не проверяется, есть ли более 2 вхождений элементов, и не является ли длина массива нечетная. Также второй пример не проверяет
null
значения, они должны быть добавлены в случае необходимости.