Ваше решение определенно соответствует критериям времени O (n).Вместо массива, который был бы очень и очень большим, если разрешенный алфавит велик (Unicode имеет более миллиона символов), вы можете использовать простой хеш.Вот ваш алгоритм в (неоптимизированном) Ruby:
def undup(s)
seen = Hash.new(0)
s.each_char {|c| seen[c] += 1}
result = ""
s.each_char {|c| result << c if seen[c] == 1}
result
end
puts(undup "")
puts(undup "abc")
puts(undup "Olé")
puts(undup "asdasjhdfasjhdfasbfdasdfaghsfdahgsdfahgsdfhgt")
Он делает два прохода через строку, и, поскольку поиск по хешу менее линейный, вы хороши.
Вы можетескажем, Hashtable (как и ваш массив) использует постоянное пространство, хотя и большое, потому что оно ограничено сверху размером алфавита.Даже если размер алфавита больше размера строки, он все равно считается постоянным пробелом.
Существует много вариантов этой проблемы, многие из которых забавны.Чтобы сделать это действительно на месте, вы можете отсортировать в первую очередь;это дает O (n log n).Существуют варианты сортировки слиянием, когда вы игнорируете ошибки во время слияния.На самом деле, это ограничение «нет внешней хеш-таблицы» появляется в Алгоритм: эффективный способ удаления дублирующихся целых чисел из массива (также помеченный как вопрос интервью).
Другой распространенный вопрос интервью начинается с простогострока, потом говорят, ладно, теперь строка из миллиона символов, ладно, теперь строка из 100 миллиардов символов и так далее.Все становится очень интересным, когда вы начинаете рассматривать большие данные.
В любом случае, ваша идея довольно хороша.Как правило, его можно настроить следующим образом: используйте набор, а не словарь.Пройдите через строку.Для каждого символа, если его нет в наборе, добавьте его.Если это так, удалите это.Наборы занимают меньше места, не нуждаются в счетчиках и могут быть реализованы в виде наборов битов, если алфавит мал, и этот алгоритм не требует двух проходов.
Реализация Python: http://code.activestate.com/recipes/52560-remove-duplicates-from-a-sequence/