Код для удаления повторяющихся символов в строке без использования дополнительного буфера. ПРИМЕЧАНИЕ. Подойдут одна или две дополнительные переменные. Дополнительный массив не является:
import java.util.*;
public class Main{
public static char[] removeDupes(char[] arr){
if (arr == null || arr.length < 2)
return arr;
int len = arr.length;
int tail = 1;
for(int x = 1; x < len; x++){
int y;
for(y = 0; y < tail; y++){
if (arr[x] == arr[y]) break;
}
if (y == tail){
arr[tail] = arr[x];
tail++;
}
}
return Arrays.copyOfRange(arr, 0, tail);
}
public static char[] bigArr(int len){
char[] arr = new char[len];
Random r = new Random();
String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+[]{}|;:',.<>/?`~";
for(int x = 0; x < len; x++){
arr[x] = alphabet.charAt(r.nextInt(alphabet.length()));
}
return arr;
}
public static void main(String args[]){
String result = new String(removeDupes(new char[]{'a', 'b', 'c', 'd', 'a'}));
assert "abcd".equals(result) : "abcda should return abcd but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'a', 'a', 'a'}));
assert "a".equals(result) : "aaaa should return a but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'b', 'c', 'a'}));
assert "abc".equals(result) : "abca should return abc but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'a', 'b', 'b'}));
assert "ab".equals(result) : "aabb should return ab but it returns: " + result;
result = new String(removeDupes(new char[]{'a'}));
assert "a".equals(result) : "a should return a but it returns: " + result;
result = new String(removeDupes(new char[]{'a', 'b', 'b', 'a'}));
assert "ab".equals(result) : "abba should return ab but it returns: " + result;
char[] arr = bigArr(5000000);
long startTime = System.nanoTime();
System.out.println("2: " + new String(removeDupes(arr)));
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Program took: " + duration + " nanoseconds");
System.out.println("Program took: " + duration/1000000000 + " seconds");
}
}
Как читать и говорить о вышеприведенном коде:
- Метод с именем removeDupes принимает массив примитивных символов с именем arr.
- arr возвращается как массив примитивных символов «по значению». Переданная arr - это сборка мусора в конце метода-члена Main removeDupes.
- Сложность времени выполнения этого алгоритма составляет O (n) или, более конкретно, O (n + (малая константа)) константа, являющаяся уникальными символами во всем массиве примитивных символов.
- copyOfRange значительно не увеличивает сложность среды выполнения, поскольку копирует только небольшое количество постоянных элементов. Массив char, называемый arr, не проходит весь путь.
- Если вы передаете значение null в removeDupes, метод возвращает значение null.
- Если вы передадите пустой массив примитивных символов или массив, содержащий одно значение, этот немодифицированный массив будет возвращен.
- Метод removeDupes идет как можно быстрее физически, полностью используя кэш L1 и L2, поэтому Перенаправления веток поддерживаются на минимальном .
- Неиспользованный компьютер стандартного выпуска 2015 года должен иметь возможность завершить этот метод с помощью массива примитивных символов, содержащего 500 миллионов символов, от 15 до 25 секунд.
Объясните, как работает этот код:
Первая часть переданного массива используется в качестве хранилища для уникальных символов, которые в конечном итоге возвращаются. В начале функции ответ: «символы от 0 до 1» от 0 до хвоста.
Мы определяем переменную y вне цикла, потому что мы хотим найти первое место, где индекс массива, на который мы смотрим, был продублирован в нашем хранилище. Когда дубликат найден, он вырывается и выходит, хвост y == возвращает false, а хранилище не добавляется.
когда индекс x, на который мы заглядываем, не представлен в нашем хранилище, тогда мы извлекаем его и добавляем в конец нашего хранилища в конце индекса и в хвосте приращения.
В конце мы возвращаем массив между точками 0 и хвостом, который должен быть меньше или равен по длине исходному массиву.
Упражнение «Говорящие точки» для интервью кодеров:
Будет ли программа вести себя иначе, если вы измените y ++ на ++ y? Почему или почему нет.
Представляет ли копия массива в конце еще один проход 'N' через весь массив, что делает сложность времени выполнения O (n * n) вместо O (n)? Почему или почему нет.
Можете ли вы заменить двойное равенство, сравнивая примитивные символы, на .equals? Почему или почему нет?
Можно ли изменить этот метод, чтобы сделать замены "по ссылке", а не как сейчас, "по значению"? Почему или почему нет?
Можете ли вы повысить эффективность этого алгоритма, отсортировав хранилище уникальных значений в начале 'arr'? При каких обстоятельствах это будет более эффективным?