Есть ли какой-либо алгоритм/метод, в котором изменение строки словами может выполняться за один проход с временной сложностью O (n) и пространственной сложностью O (1).Переключение строк по слову за один проход
ответ
Если мы можем получить символы в обратном порядке, и каждое слово требует не более O(1)
машинных слов в памяти, то для обратного слова в один проход можно использовать O (n) -time, O (1) -пространственный алгоритм (псевдо-код):
def reverse_words(text):
word = [] # assume a word requires O(1) machine words
for character in reversed(text): # single pass (in reverse)
if character == ' ':
if word: # print non-empty word
print(''.join(reversed(word)), end=character)
word = []
else:
word.append(character) # O(1)-time
if word: # print the first word (in original text) if it is not empty
print(''.join(reversed(word)))
Пример:
>>> reverse_words("this is a string")
string a is this
Примечание: каждый символ прикоснулся дважды: первый - добавление, второй - распечатать его. Чтобы понять, почему это еще однопроходный алгоритм, представьте вместо text
функцию poplast()
, которая выводит (извлекает и удаляет) последний символ из последовательности символов. Если она возвращает None
для пустой последовательности, то цикл будет выглядеть так:
for character in iter(poplast, None): # call `poplast()` until it returns `None`
# the rest is the same as in the first loop ..
В этом случае мы не можем сделать больше, чем один проход над входом. Он разрушается на первом проходе.
возможно ли изменить исходный текст?
Да. Снова , если можно считать, что длина длинного слова постоянна (не зависит от n
), т. Е. Если n
растет; максимальная длина слова остается неизменной.
Просто прочитайте одно слово за раз с обоих концов на два временных буфера. И поменяйте их, сохранив следы неиспользуемых концов из-за неравномерных размеров слов на разных концах. Только один временный буфер не будет пустым после обмена (тот, у которого есть неполное слово). Заполняйте буферы до тех пор, пока не будет найдено полное слово на обоих концах или в центре. Затем повторите своп.
Я не могу придумать элегантную реализацию. И я не вижу смысла однопроходного требования, если у нас есть случайный доступ к вводу. Посмотрите, как реализованы tac
utility or tail -r
(BSD) (в этом случае строка играет роль одного слова) для очень больших файлов, которые не вписываются в память.
@ Dukeling: Это единственный проход. Представьте, что 'reverse (text)' * никогда не заканчивается *. Функция все еще работает. Единственное «большое» предположение состоит в том, что слова конечны. – jfs
Поцарапайте мой последний комментарий. Предположение, что длины слов имеют (постоянную) верхнюю границу, не является необоснованным, но с теоретической точки зрения (ради интереса или для интервью) я не думаю, что это должно быть сделано. И «слово», возможно, не предназначалось для обозначения значимой последовательности символов, а всего лишь последовательность символов. Кроме того, это печатает его, а не помещает символы обратно в одну строку (последнее может быть желательным и невозможно было бы здесь в O (1)). – Dukeling
@ J.F.Sebastian. Если задано обращение слов, это можно сделать за один проход, но мне нужно, чтобы строка shld была обращена словами только в «одном проходе». – Abhishek
Нет, это невозможно за один проход, если вы уже не знаете, сколько времени у каждого слова или разрешено использовать какой-то буфер.
Попробуйте:
HELLO SAM
^
becomes
SAM HELLO
^
Если все, что вы знаете, это E
(так как это ваш первый/единственный проход, и вы не можете хранить любые данные), вы можете не знать, что, возможно, он должен быть заменен туда, где в данный момент находится символ пробела. Как только вы достигнете места и узнаете, где находится E
, слишком поздно снова получить E
.
@ Dukeling: Я говорю о последнем (иначе вы бы знали, что позиция просто «n-i-1»), и я изменил этот пример, чтобы устранить любую двусмысленность. Благодаря! –
Если длина слова ограничена (не зависит от 'n'), то вы можете прочитать до конца слова. И [O (n) -time однопроходный, O (1) -пространственный алгоритм возможен] (http://stackoverflow.com/a/20649255/4279). – jfs
Если рассматривать слово может иметь максимальное количество символов 20, мы можем достичь O (1) пространство, O (N) времени и один проход :)
public static void main(String[] args) {
reverse("Hello World HaHa");
}
public static void reverse(String line) {
char[] stack = new char[20];
int index = 0;
for (int i = line.length() - 1; i >= 0; i--) {
if (line.charAt(i) != ' ') {
stack[index++] = line.charAt(i);
} else {
while (--index >= 0) {
System.out.print(stack[index]);
}
System.out.print(' ');
index = 0;
}
}
if (index > 0) {
while (--index >= 0) {
System.out.print(stack[index]);
}
}
}
Примечание: фактическая сложность времени is 2n, где n - длина строки, но один проход!
Я считаю, что это тот же подход, что и [ответ J.F.] (http://stackoverflow.com/a/20649255/1711796). Заметьте [мой комментарий там] (http://stackoverflow.com/questions/20648333/string-reversal-by-word-in-single-pass?noredirect1_comment30917729_20649255). – Dukeling
@Pham Trung, вы используете buffer.So это не будет содержать пространственную сложность O (1). – Abhishek
@Abhishek: любой буфер фиксированного размера ('20' в этом случае), который не зависит от' n', удовлетворяет требованиям 'O (1)' space. Вы можете сказать, что код не работает, если слово больше 20 символов. Но ваш вопрос ничего не говорит о возможном размере слова. – jfs
- 1. Распакуйте за один проход?
- 2. Сделайте это за один проход?
- 3. log4net один файл за один проход
- 4. поиск мин/макс с pyspark за один проход по данным
- 5. C++ заменить несколько строк в строке за один проход
- 6. C# - соответствует многим случаям за один проход
- 7. Удаление B-Tree за один проход
- 8. Ruby: изменить XML-файл за один проход
- 9. Вычисление статистики по генераторам за один проход. Python
- 10. Как эффективно один проход подсчета строк по dataframe
- 11. SUM ПЕРЕГОВОРИМОСТЬ И ГРУППА за один проход?
- 12. Ссылка на вставленные элементы за один проход
- 13. Выполнение более одного сокращения за один проход
- 14. Изменение содержимого div дважды за один проход
- 15. Назначение и возврат переменной за один проход
- 16. MySQL UPDATE и SELECT за один проход
- 17. Нарисуйте кубический файл за один проход OpenGL
- 18. Как удалить несколько столбцов за один проход
- 19. фильтрованные и нефильтрованные элементы за один проход
- 20. SQL Match Несколько запросов за один проход
- 21. Скребок HTML с XPath за один проход
- 22. LINQ пытается решить все за один проход?
- 23. О обработке промежуточных операций за один проход?
- 24. Комбинируйте grep и sub за один проход?
- 25. Обновить и выбрать за один проход
- 26. копия файла быстрее за один проход
- 27. среднее и дисперсия изображения за один проход
- 28. Как заменить несколько вхождений за один проход?
- 29. Индекс solr, возвращает предложения по одному слову за один раз
- 30. Могу ли я использовать несколько объектов за один проход?
Вы могли бы добавить простой пример ввода/вывода? – RichardPlunkett
@RichardPlunkett Это разворот строк. Выберите несколько слов. –
вход: Hello world output: world hello – Abhishek