Трудный вопрос на собеседовании #3
Александр СкакуновОпубликовано 16.06.2008 в Статьи
Продолжаем серию переводов цикла “Трудные вопросы на собеседовании“.
Задача #3
Как вы обернете порядок слов (не символов) в строке длиной n при постоянном объеме дополнительной памяти (constant extra space) за линейное время (linear time)?
UPDATE: ответ.
Понравилась статья? Подпишись на обновления по RSS/E-mail



Я б виділяв по слову з початку та кінця рядка, а тоді міняв їх місцями через додаткову пам’ять. І так, до зустрічі вказівників у середині рядка.
Хоча, я не до кінця зрозумів обмеження constant extra space.
pregsplit на слова и реверс массива слов.
На счет памяти тоже не понял, что имелось в виду? кол-во байт и операции только с массивом символов?
Насколько я могу судить, “constant extra space” – расхожее понятие в области сортировки. Есть даже книжка “Constant-space string-matching“:
Пусть есть такая функция оборота части строки (псевдокод, str – строка, s – начальный индекс, e – конечный):
function reverse(str, s, e) {
for(i = s; i < e/2; i++) {
buf = str[i];
str[i] = str[e - i + 1];
str[e - i + 1] = buf;
}
}
Первым делом оборачиваем всю строку:
reverse(str, 0, n)
Затем последовательно находим границы слов (s_word, e_word) и для каждого вызываем:
reverse(str, s_word, e_word)
Вот как-то так примерно
Sorry за отвутствие отступов, пробую еще раз только функцию:
Хм… я ожидал что code сохранит форматирование
Да, добавлю сразу – str передается в функцию по ссылке.
ruby:
string.split.reverse.join(” “)
Прикольно
Правда, не соблюдено условие задачи – “constant extra space”, т.к. используется массив переменной длины.
если используется массив той же длины что и строка, то это constant extra space?
оценка времени выполнения меня удручает
Перевертнуть всю строку, а потом перевернуть символы в каждом слове.
C++
Упс, все-таки треба тестити спочатку.
>> если используется массив той же длины что и строка, то это constant extra space?
це linear extra space.
Поприветствуем Олексия Орешко, координатора TopCoder!
Олексий, могли бы вы авторитетно объяснить, что такое этот constant extra space? Ибо народ конфузится, хотя ответы пишет правильные.
Константна додаткова пам’ять (constant extra space) – розмір якої не залежить від розміру вхідних даних.
Лінійна додаткова пам’ять (constant extra space) – розмір якої лінійно залежить від розміру вхідних даних.
Звичайно, всі ці визначення мають на увазі пам’ять у найгіршому для вашої програми випадку.
Простими словами. Візьмемо вхідні дані (в нашому випадку – рядок) і почнемо їх збільшувати (дописувати до рядка символи). Якщо при кожному збільшенні рядка в два рази пам’ять збільшиться вдвічі – то це лінійна залежність. Якщо не зміниться ніяк – то пам’ять константна. Аналогічно з часом виконання.
Спробую пояснити на пальцях про “constant extra space”.
Якщо вашій програмі для обробки вхідних даних довжиною в одну букву (1 слово з однієї букви) необхідно виділити блоки пам’яті сумарним розміром в 1 МБ але коли на вхід передали стрічку, що містить 4 Мільярди слів по 100 букв у кожному слові – програмі все ще буде достатньо цього ж 1 МБ додаткової пам’яті.
У випадку
ruby:
string.split.reverse.join(” “)
Потрібно буде виділити масив, розмір якого залежить від вхідних даних а також створити копії всіх слів в стрічці і помістити їх у цей масив. Відповідно, оцінити розмір додаткової мам’яті не знаючи розміру вхідної стрічки – неможливо.
2 Саша
>>Відповідно, оцінити розмір додаткової мам’яті не знаючи розміру вхідної стрічки – неможливо.
Наскільки я зрозумів, то пам’ять має бути лінійна як мінімум (копія всього ). Хоча, з іншого боку, мова програмування може оптимізувати деякі операції.
Формальне визначення константної додаткової пам’яті.
Пам’ять константна (не залежить від входу), якщо існує такий об’єм пам’яті Х, що ваша програма не потребуватиме більше Х при жодних вхідних даних.
Пам’ять лінійна, якщо існує таке число Х, що ваша програма ніколи не потребуватиме більше, ніж Х * (розмір вхідних даних).
>> Раковець Олександр
Я б виділяв по слову з початку та кінця рядка, а тоді міняв їх місцями через додаткову пам’ять.
Тут обмеження на пам’ять може бути лінійним, якщо дати на вхід одне величезне слово (рядок без пробілів). Крім того, не розкрита тема обміну місцями слів різної довжини.
похоже на задачки с алгоритмической олимпиады…
Сорри за пост 21. 22+23 моё решение.
P.S: Непонимаю почему в один не влезает..=(
Хмм…цикл такой for(unsigned i = 0; i < len; ++i)…
2 Olexiy
>> Наскільки я зрозумів, то пам’ять має бути лінійна як мінімум (копія всього ).
Копію всього робити непотрібно, оскільки результат роботи ф-ї записується в той же масив, де були вхідні дані.
>> Мова програмування може оптимізувати деякі операції.
Оптимізувати може компілятор (а не мова програмування). Оптимізація НІКОЛИ не рообить з неправильної програми – правильну і не змінює складність алгоритму (лінійний, логарифмічний).
Компілятор може лише замінювати деякі елементарні (з точки зору мови програмування) операції на еквівалентні або ж викидати частини коду що не впливають на результат.
2 Саша
>> Потрібно буде виділити масив, розмір якого залежить від вхідних даних а також створити копії всіх слів в стрічці і помістити їх у цей масив.
Наскільки я зрозумів це речення, то копії всіх слів одночасно перепишуться в масив – тобто, власне, весь вміст входу (за виключенням пробілів) буде переписано.
Щодо оптимізації – я мав на увазі, що деталі реалізації можуть суттєво відрізнятись. Крім того, якщо ми використовуємо деякі бібліотечні методи, то деталі їх реалізації, очевидно, напряму впливає на складність кінцевої програми.
Как я понял условие:
Есть только ваша строка, никакой дополнительной памяти (даже копии строки), кроме како-то константного (5-10) кол-ва переменных (long”ов, например) быть не может.
Таким образом, строку нельзя ни разрезать, ни вставлять в нее ничего. Можно лишь только менять 2 символа с i и j позиций.
В таком ракурсе решение:
1. Просто развернуть строку
Кому не нравится, можете вынести char a за цикл.
Всего : Один проход по строке.
2. В полученной строке поразворачивать слова.
Это реализуется с помощью двух указателей, первый – на начало слова, другой на конец. Разворот такой же, как и в пункте 1.
Еще раз алгоритм, бо система делает текст по дыбильному написанным
Всего 3 прохода по строке. (1 – пункт один, 2 и 3-в вайле, просто разворот каждого слова по сути добавляет еще один проход)
чуваки сорри за and, должно быть &&, привык у ся передефайнивать
Эх. оказуется, ее уже решили идейно в посте 11….сорри за офтоп
2 raggzy: Співбесіда ж на ІТ-позицію, а не на філолога – так що код потрібен
прикол, решение сразу же было дано, но обсуждение не заканчивается, собрались звери
просто рвут задачу на куски
@ай,
5 баллов ))
2 raggzy
У тебе, до речі, якщо рядок (після розвороту) закінчується словом, то це останнє слово буде написано ззаду наперед. Приклад: на “ab cd” видасть “cd ba”.
2 Щетинин
Привіт Малюк, як життя?
Привет Орех, дела хорошо, как у тебя?
Да… помню задавал на собеседовании такую задачку )) пока что результат 50% .. правда решил ее давать только 2 челам )) обычно до нее дело не доходит..
Итак, правильный ответ:
За проявленную активность администрация developers.org.ua рада вручить футболку Олексию Орешко.
Це буде більше ніж лінійний час, чи я помиляюся?