Как составить тестовое задание для программиста

Занимаясь одбором кандидатов на вакансию программиста, столкнулся с проблемой — подобрать хорошее тестовое задание. Цель — увидеть, программист ли передо мной или человек, хорошо знающий фреймворкязыктехнллогию. Поясню — программист, это человек, которые может решить нетривиальную проблему. Сделать сайт-блог, даже e-commerce сейчас является тривиальной проблемой, на это способен любой junior. Natural-born программистдумает по-другому.

под катом образец тестового задания

Звучит так:

Пожалуйста, разработайте функциюкласс для «перемешивания» предложения.

Символ | является разделителем слов-вариантов. Например:

«{Пожалуйста|Просто} сделайте так, чтобы это {удивительное|крутое|простое} тестовое предложение {изменялось {быстро|мгновенно} случайным образом|менялось каждый раз}.»

На выходе должно получаться:

Пожалуйста сделайте так, чтобы это крутое тестовое предложение изменялось каждый раз.
или
Просто сделайте так, чтобы это удивительное тестовое предложение изменялось мгновенно случайным образом.

Скажу сразу, что насмотрелся я много, вплоть до хардкод-массива всех возможных вариантов с выбором одного случайного, так что задание действовало. Однако «продвинутые» товарищи находят решение в интрнете и копипастят. Пользы нету от этого никому. Если кто-то когда-то выполнял интересное нетривиальное задание — буду премного благодарен. (либо в коменты либо в ЛС).

При приеме сотрудника в офис на должность программиста, работодатель испытывает кандидата не только вопросами о навыках, но и всевозможными логическими задачами, IT-кейсами и заданиями по разработке для профессиональных программистов. Как правило, список этих задач у работодателей совпадает, а значит, мы можем подготовиться к любому собеседованию!

В нашей рубрике c заданиями уже больше 100 вопросов с подробным разбором решений. Мы решили собрать воедино все самые интересные и популярные задачи для программистов, которые могут встретиться вам на собеседовании.

Есть однонаправленный список из структур. В нём random указывает на какой-то еще элемент этого же списка. Требуется написать функцию, которая копирует этот список с сохранением структуры (т.е. если в старом списке random первой ноды указывал на 4-ю, в новом списке должно быть то же самое – рандом первой ноды указывает на 4-ю ноду нового списка). O(n), константная дополнительная память + память под элементы нового списка. Нельзя сразу выделить память под все данные одник куском т.е. список должен быть честным, разбросанным по частям, а не единым блоком, как массив.

Ответ Вариант реализации

Классическая задачка с собеседований в Google. На доске записаны числа, вам нужно ответить на вопрос: какое число идёт дальше?
задача какое число идет дальше

Ответ

Допустим, вы летите из Москвы во Владивосток, а затем обратно, при полном безветрии. Затем вы совершаете точно такой же перелёт, но на этот раз на протяжении всего перелёта дует постоянный западный ветер: в одну сторону попутный, в обратную — лобовой.

Ответ

Что не так в этом отрывке кода на С++?

operator int() const {
    return *this;
}

Ответ

Задача, которая была популярна в своё время на собеседованиях в Amazon. Мы русифицировали её, но смысл остался тот же. Вам нужно продолжить последовательность.

задача продолжите последовательность

Ответ автора с обзором вариантов ответов подписчиков

Как это вычислить, не пользуясь калькулятором? Можете дать приблизительный ответ?

задача, как вычислить без калькулятора

Ответ

«Вас уменьшили до размеров 5-центовой монеты и бросили в блендер. Ваш вес уменьшился так, что плотность вашего тела осталась прежней. Лезвия начнут вращаться через 60 секунд. Ваши действия?»

Это классическая google-задачка, хороший разбор которой в рунете не так-то просто найти. Мы подготовили его для вас. Абсолютного правильного ответа нет, но есть те, которые явно лучше остальных.

Разбор вариантов ответа

Вопрос по С++. Что за ошибка «pure virtual function call»? В какой ситуации она может быть сгенерирована? Предоставьте минимальный код, приводящий к ней.

Ответ

В вашем распоряжении 10 тысяч серверов в дата-центре с возможностью удалённого управления и один день, чтобы получить миллион долларов. Что вы для этого сделаете?

Ответ

У вас есть аналоговые часы с секундной стрелкой. Сколько раз в день все три стрелки часов накладываются друг на друга?

задача часы

Ответ

В чём разница между string и String в C#?

С#: string vs. String

Ответ

Вы играете в футбол на пустынном острове и хотите подбросить монетку, чтобы решить, какой команде достанется мяч. Единственная монета, что у вас есть, является гнутой, и поэтому вносит явные искажения в результат при подбрасывании. Как вы тем не менее можете использовать такую монету, чтобы принять справедливое решение?

Ответ

Cколько мячей для гольфа войдет в школьный автобус?

Для справки: в Национальных стандартах транспотрных средств для школ в США на 1995 год указаны максимальные размеры школьного автобуса и равны 40 футам в длину и 8.5 футам в ширину. Стандартный диаметр мяча для гольфа — 1.69 дюйма с допуском 0.005 дюймов.

Ответ

Представьте себе вращающийся диск, например DVD. У вас есть в распоряжении черная (Ч) и белая (Б) краски. На краю диска установлен небольшой датчик, который определяет цвет под ним и выдает результат в виде сигнала. Как бы вы раскрасили диск, чтобы было возможно определить направление вращения по показаниям датчика?

задача датчик

Дадим небольшое пояснение к задаче. Первое, что нужно иметь ввиду, это то, что нельзя наблюдать за самим диском. Например, вы сидите в офисе, а диск вращается в закрытой лаборатории. Единственная возможность определить направление вращения — использовать оцифрованные показания датчика, и ничего больше.

Датчик фиксирует цвет точки в непосредственном месте установки в последовательные моменты времени. Показания представляются в виде «ЧЧЧББ…». Задача сводится к такой раскраске диска, где последовательность показаний отличается при вращении в прямую и в противоположную стороны.

Ответ

У вас есть исходный код приложения на языке С, которое аварийно завершается после запуска. После десяти запусков в отладчике вы обнаруживаете, что каждый раз программа падает в разных местах. Приложение однопоточное и использует только стандартную библиотеку С. Какие ошибки могут вызвать падение приложения? Как вы проверите каждую?

Ответ

Найдите ошибки в следующем коде.

unsigned int i;
for (i = 100; i >= 0; --i)
    printf("%d
", i);

Ответ

Объясните, что делает этот код.

((n & (n – 1)) == 0)

Ответ

Дано 100-этажное здание. Если яйцо сбросить с высоты N-го этажа (или с большей высоты), оно разобьется. Если его бросить с любого меньшего этажа, оно не разобьется. У вас есть два яйца. Найдите N за минимальное количество бросков.

Ответ

Продолжаем задачки по С/С++. Что означает ключевое слово volatile и в каких ситуация оно может быть применено? Если даже помните формальное значение, попробуйте привести пример ситуации, где volatile на самом деле будет полезно.

Ответ

У вас есть отсортированная матрица размера MxN. Предложите алгоритм поиска в ней произвольного элемента. Под отсортированной матрицей будем понимать такую матрицу, строки и столбцы которой отсортированы (см. пример).

задача как найти элемент 55

Ответ

Напишите метод, находящий максимальное из двух чисел, не используя операторы if-else или любые другие операторы сравнения.

Ответ

На пустынном шоссе вероятность появления автомобиля за 30-минутный период составляет 0.95. Какова вероятность его появления за 10 минут?

Ответ

Напишите функцию суммирования двух целых чисел без использования «+» и других арифметических операторов.

Ответ

У вас есть парк из 50 грузовиков. Каждый из них полностью заправлен и может проехать 100 км. Как далеко с их помощью вы можете доставить определенный груз? Что будет, если в вашем распоряжении N грузовиков?

Не все понимают сразу о чем речь: территориально это место, где нет никаких заправочных станций. Единственное место, где можно здесь найти горючее – это топливные баки грузовиков. Пересесть из грузовика в гибридный легковой автомобиль Prius нельзя. Бросить грузовик без топлива, где бы это ни случилось, и без водителя – в порядке вещей. И единственное, что здесь важно, – доставить как можно дальше ценный груз.

Ответ

Опишите алгоритм для нахождения миллиона наименьших чисел в наборе из миллиарда чисел. Память компьютера позволяет хранить весь миллиард чисел. Если придумали какое-либо решение, то оцените его эффективность по времени. Есть ли более эффективное решение?

Ответ

Напишите метод, который будет подсчитывать количество цифр «2», используемых в десятичной записи целых чисел от 0 до n (включительно). Картинка дана в качестве подсказки к одному из возможных решений.

подсказка к одному из возможных решений

Ответ

Где вы будете плыть быстрее — в воде или сиропе?

Это классическая задача с долгой историей, которую обсуждал в своё время еще Исаак Ньютон. Когда-то она использовалась и на IT-собеседованиях в Google (сейчас — нет). Тем не менее предлагаем вам порассуждать над решением.

Ответ

Напишите методы для умножения, вычитания и деления целых чисел, используя из арифметических операций только оператор суммирования. Язык реализации не важен, об оптимизации скорости работы и использования памяти также можете не особо беспокоиться. Главное, что можно использовать только сложение. В подобных задачах полезно вспомнить суть математических операций.

Ответ

Допустим, вы пишете конвейер, в котором 2 потока, используя общий буфер, обрабатывают данные. Поток-producer эти данные создает, а поток-consumer их обрабатывает (Producer–consumer problem). Следующий код представляет собой самую простую модель: с помощью std::thread мы порождаем поток-consumer, a создавать данные мы будем в главном потоке.

Опустим механизмы синхронизации двух потоков, и обратим внимание на функцию main(). Попробуйте догадаться, что с этим кодом не так, и как его исправить?

void produce() {
    // создаем задачу и кладем в очередь
}
 
void consume() {
    // читаем данные из очереди и обрабатываем
}
 
int main(int , char **) {
    std::thread thr(consume); // порождаем поток
    produce(); // создаем данные для обработки
    thr.join(); // ждем завершения работы функции consume()
    return 0;
}

Ответ

Дано 20 баночек с таблетками. В 19 из них лежат таблетки весом 1 г, а в одной – весом 1.1 г. Даны весы, показывающие точный вес. Как за одно взвешивание найти банку с тяжелыми таблетками?

Ответ

Дана шахматная доска размером 8×8, из которой были вырезаны два противоположных по диагонали угла, и 31 кость домино; каждая кость домино может закрыть два квадратика на поле. Можно ли вымостить костями всю доску? Дайте обоснование своему ответу.

задача шахматная доска и домино

Ответ

Дан входной файл, содержащий четыре миллиарда целых 32-битных чисел. Предложите алгоритм, генерирующий число, отсутствующее в файле. Имеется 1 Гбайт памяти для этой задачи. Дополнительно: а что если у вас всего 10 Мбайт? Количество проходов по файлу должно быть минимальным.

Ответ

Предложите алгоритм, генерирующий все корректные комбинации пар круглых скобок. Под корректными комбинациями пар будем понимать правильно открытые и закрытые скобки. На вход подаётся число пар скобок, на выходе должны быть все возможные их комбинации в виде набора строк.

Ответ

Вы поставили стакан воды на диск проигрывателя виниловых пластинок и медленно увеличиваете скорость вращения. Что произойдет раньше: стакан сползет в сторону, стакан опрокинется, вода расплескается?

Этот вопрос задавали ранее на собеседованиях в Apple. При ответе рассмотрите возможные варианты и укажите, от чего зависит ответ, если их несколько.

Ответ

Короткая задачка по С++ в виде вопроса для новичков. Почему деструктор полиморфного базового класса должен объявляться виртуальным? Полиморфным считаем класс, в котором есть хотя бы одна виртуальная функция.

Ответ

Напишите функцию, меняющую местами значения переменных, не используя временные переменные. Предложите как можно больше вариантов.

Ответ

Предложите алгоритм поиска в односвязном списке k-го элемента с конца. Список реализован вручную, есть только операция получения следующего элемента и указатель на первый элемент. Алгоритм, по возможности, должен быть оптимален по времени и памяти.

Ответ

Напишите функцию, определяющую количество битов, которые необходимо изменить, чтобы из целого числа А получить целое число B. Числа, допустим, 32-битные, язык любой.

Это одна из типичных задач на работу с битами, которые любят давать на собеседовании. Если вы никогда с ними не сталкивались, вам будет сложно сразу решить задачу с учётом стрессовой ситуации, поэтому запомните использованные при решении трюки.

Ответ

В книге N страниц, пронумерованных как обычно от 1 до N. Если сложить количество цифр, содержащихся в каждом номере страницы, будет 1095. Сколько страниц в книге?

Ответ

Задачка по С++, которая, тем не менее, будет полезна и для других языков. Сопоставьте хэш-таблицу и mар из стандартной библиотеки шаблонов (STL). Как организована хэш-таблица? Какая структура данных будет оптимальной для небольших объемов данных?

Ответ

Разработайте класс, обеспечивающий блокировку так, чтобы предотвратить возникновение мертвой блокировки.

Ответ

Напишите функцию на С++, выводящую в стандартный поток вывода K последних строк файла. При этом файл очень большой, допустим 50 ГБ, длина каждой строки не превышает 256 символов, а число K < 1000.

Ответ

Дан кусок сыра в форме куба и нож. Какое минимальное количество разрезов потребуется сделать, чтобы разделить этот кусок на 27 одинаковых кубиков? А на 64 кубика? После каждого разреза части можно компоновать как угодно.

Такую задачку раньше часто давали на собеседованиях, а придумана она была ещё в 1950 году.

Ответ

Реализуйте метод, определяющий, является ли одна строка перестановкой другой. Под перестановкой понимаем любое изменение порядка символов. Регистр учитывается, пробелы являются существенными.

Ответ

В тёмной комнате вам вручают колоду карт, в которой известное количество карт N лежат рубашкой вверх, а остальные — вниз. Вы не можете видеть карты, но можете их переворачивать. Как вы разделите колоду на две стопки, чтобы в каждой из них было одинаковое число карт, лежащих рубашкой вверх?

Эта головоломка в своё время была популярна в JP Morgan Chase. Понятное дело, оказавшись в темноте, вы просто достанете сотовый телефон и воспользуетесь экраном как фонариком. Однако эта задачка появилась до эпохи сотовых телефонов, и её можно решить, даже не видя карт.

Ответ

Реализуйте вручную стек со стандартными функциями push/pop и дополнительной функцией min, возвращающей минимальный элемент стека. Все эти функции должны работать за O(1). Решение оптимизируйте по использованию памяти.

push-pop2

Ответ

У скольких целых чисел, лежащих в диапазоне от 1 до 1000, есть цифра 3? Посчитать нужно без использования компьютера, приведя свои рассуждения в комментариях.

Ответ

У вас есть много URL-адресов, порядка 10 миллиардов. Как бы вы организовали эффективный поиск дубликатов, учитывая, что все они, конечно же, не поместятся в памяти?

Ответ

Вы должны выбрать одну из двух ставок. При первом варианте вы должны забросить баскетбольный мяч в корзину за один бросок. Если попадёте, то получите 50 тыс. рублей. Во втором варианте вам надо попасть два раза из трёх бросков, и тогда вы также получите те же 50 тыс. рублей. Какой из этих вариантов вы предпочтёте? Будет ли ваше умение забрасывать мячи влиять на выбор?

Ответ

Представьте себе треугольник, составленный из чисел. Одно число расположено в вершине. Ниже размещено два числа, затем три, и так до нижней грани. Вы начинаете на вершине, и нужно спуститься к основанию треугольника. За каждый ход вы можете спуститься на один уровень и выбрать между двумя числами под текущей позицией. По ходу движения вы «собираете» и суммируете числа, которые проходите. Ваша цель — найти максимальную сумму, которую можно получить из различных маршрутов.

Какой алгоритм вы предложите? Какая у него будет сложность и можно ли предложить лучший вариант?

golden-pyramid-example

Ответ

Даны два слова или фразы, и ваша задача — проверить, являются ли они анаграммами.

Анаграмма — это игра со словами, когда в результате перестановки букв слова или фразы получаем другое слово или фразу. Два слова являются анаграммами, если мы можем получить одно из другого переставляя буквы местами.

anagramm

Ответ

Предложите алгоритм, который обнуляет столбец N и строку M матрицы, если элемент в ячейке (N, M) нулевой. Конечно же, нужно минимизировать затраты памяти и время работы.

Ответ

Разработайте алгоритм, обнаруживающий в массиве все пары целых чисел, сумма которых равна заданному значению.

Ответ

Предположим, вам нужно разработать алгоритм, демонстрирующий круг знакомств человека для социальных сетей. Как бы вы это сделали, при условии, что база очень большая?

Под большой базой подразумевается порядка миллиарда зарегистрированных пользователей и не менее 100 миллиардов «дружеских» связей между ними.

Ответ

Допустим, у вас есть однонаправленный список с петлёй. Его «последний» элемент содержит указатель на один из элементов этого же списка, причём не обязательно на первый. Ваша задача — найти начальный узел петли.

Элементы списка менять нельзя, память можно использовать только константную.

Ответ

На острове существует правило — голубоглазые люди не могут там находиться. Самолет улетает с острова каждый вечер в 20:00. Все жители собираются за круглым столом ежедневно, каждый человек может видеть цвет глаз других людей, но не знает цвет собственных. Никто не имеет права сказать человеку, какой у него цвет глаз. На острове находится не менее одного голубоглазого человека. Сколько дней потребуется, чтобы все голубоглазые уехали?

Ответ

Напишите код, удаляющий дубликаты из несортированного связного списка. Можно использовать только константную память.

Doubly_linked_list-870x295

Ответ

Напишите метод, тасующий карточную колоду. Колода должна быть идеально перемешана т.е. перестановки карт должны быть равновероятными. Вы можете использовать идеальный генератор случайных чисел.

Ответ

Допустим, вам поручили задачу по разработке поискового робота — программы, которая, грубо говоря, посещает страницы в Интернете, индексирует, выделяет из них ссылки, переходит по ним и повторяет процесс. Вопрос: как избежать зацикливания?

Ответ

У вас есть стеклянный кувшин, в котором лежат небольшие шарики, и вы в любое время можете определить их количество. Вы со своим другом играете в следующую игру: каждый из вас по очереди забирает из кувшина 1 или 2 шарика. Игрок, который забирает последний шарик, выигрывает. Какая самая лучшая стратегия в этой игре? Можете ли вы в самом начале предсказать, кто выиграет?

Ответ

Имеется N компаний, и вы хотите, чтобы они слились и образовали одну крупную компанию. Сколько разных способов вы можете использовать для этого? Поглощение можно считать частным случаем слияния, когда А поглощает Б и Б полгощает А — два разных способа. Равнозначные слияния тоже возможны.

Ответ

Какой минимальный комплект монет необходим для того, чтобы выдать любую сдачу от 1 до 99 центов? Доступные номиналы монет: 1, 5, 10, 25, 50 центов и 1 доллар.

Ответ

У вас есть 25 лошадей. Сколько забегов вам нужно устроить, чтобы определить трех самых быстрых из них? Вы не можете пользоваться секундомером. В каждом заезде могут участвовать только пять лошадей.

Ответ

Короткая задачка на сообразительность. По результатам исследования известно, что 70% людей любят кофе, в то же время 80% любят чай. Каковы верхние и нижние границы доли людей, которые одновременно любят кофе и чай?

Ответ

Задачка, которую нужно решать без калькулятора и компьютера, имея под рукой только карандаш и бумагу. Сколько нулей в конце факториала 100?

Ответ

Предложите алгоритм нахождения самой большой суммы непрерывной последовательности из массива целых чисел, как положительных, так и отрицательных.

Ответ

Напишите программу расчета значения медианы в потоке чисел, динамически отслеживающую новые поступающие числа, получаемые рандомом.

Ответ

Идет дождь, а вам надо добраться до вашей машины, которая стоит в самом дальнем конце парковки. Побежите ли вы к ней или нет, если ваша цель — как можно меньше промокнуть? Как вы будете себя вести, если у вас есть зонтик?

Ответ

Представьте, что существует квадратная матрица, каждый пиксель которой может быть черным или белым. Разработайте алгоритм поиска максимального субквадрата, у которого все стороны черные.

Разбор двух вариантов решения за O(N^4) и O(N^3). Можете ли вы найти другие варианты?

Ответ

Предположим, в некоторый бар ходят только необщительные посетители. Вдоль барной стойки расположены 25 мест. Всякий раз, когда входит новый посетитель, он обязательно садится на самое дальнее, насколько это возможно, место от остальных гостей. Ни один не сядет рядом с кем-то другим: если посетитель входит и видит, что «свободных» мест нет, он тут же разворачивается и уходит из бара. Бармену, естественно, хочется, чтобы за стойкой сидело как можно больше клиентов. Если ему разрешено усадить первого посетителя на любое место, куда выгоднее его посадить с точки зрения бармена?

Ответ

Опишите, как можно использовать один одномерный массив для реализации трех стеков.

Ответ

У вас есть неограниченное количество монет достоинством 25, 10, 5 и 1 цент. Напишите код, определяющий количество способов представления n центов.

Ответ

Напишите код, который позволяет найти минимальное расстояние (выражаемое количеством слов) между любыми двумя словами в файле. Порядок не важен.

задача написать код для поиска минимального расстояния между словами

Достаточно ли будет линейного времени?
Сколько памяти понадобится для решения?

Ответ

Смоделируйте использование игральной кости с семью гранями, если в вашем распоряжении имеется только кость с пятью гранями.

Иными словами, как получить случайное число в диапазоне от 1 до 7, используя генератор случайных целых чисел от 1 до 5?

Ответ

Напишите код, разбивающий связный список вокруг некоторого значения так, чтобы все меньшие узлы оказались перед узлами, большими или равными этому значению.

Ответ

Напишите метод, генерирующий случайную последовательность m целых чисел из массива размером n. Все элементы выбираются с одинаковой вероятностью.

Первое, что приходит в голову, — выбрать случайные элементы из массива и поместить их в новый массив. Но что если мы выберем один и тот же элемент дважды?

Ответ

Представьте себе робота, находящегося в левом верхнем углу сетки с координатами (X, Y). Робот может перемещаться в двух направлениях: вправо и вниз. Сколько существует маршрутов, проходящих от точки (0, 0) до точки (X, Y)?

Дополнительно предположите, что на сетке существуют области, которые робот не может пересекать. Разработайте алгоритм построения маршрута от левого верхнего до правого нижнего угла.

Ответ

Реализуйте метод сжатия строки на основе счетчика повторяющихся символов. Например, строка aabcccccaaa должна превратиться в а2b1с5аЗ. Если «сжатая» строка оказывается длиннее исходной, метод должен вернуть исходную строку.

Ответ

Вы находитесь в автомобиле, где к полу веревочкой привязан шар, наполненный гелием. Окна закрыты. Вы нажимаете на педаль газа. Что произойдет с шаром: переместится он вперед, назад или останется в прежнем положении?

car

Ответ

Задачка, на примере который можно кратко ознакомиться с основами RSA-криптографии.

Допустим, вы хотите удостовериться, что у вашего друга Пети есть номер вашего телефона. Но вы не можете спросить его об этом прямо. Вам придется написать ему сообщение на карточке и отдать карточку Кате, которая будет выступать в качестве посредника. Катя отнесет карточку Пете, он напишет свое сообщение и отдаст его Кате, которая передаст его вам. Вы не хотите, чтобы Катя узнала ваш номер телефона. Как в таких обстоятельствах следует сформулировать свой вопрос Пете?

Даже не зная ничего про RSA можно попробовать придумать ответ.

Ответ

Задача на знание конкретных языков. Объясните разницу между шаблонами в C++ и дженериками в Java.

Многие программисты полагают, что шаблоны C++ и дженерики (например в Java) — это одно и то же, ведь их синтаксис похож: в обоих случаях можно написать что-то вроде List<T>. Но различия на самом деле есть.

Ответ

Реализуйте вручную «умный» указатель с автоматическим управлением памятью на C++.

Умный (интеллектуальный) указатель — это тот же обычный указатель, обеспечивающий безопасность благодаря автоматическому управлению памятью. Такой указатель помогает избежать множества проблем: «висячие» указатели, «утечки» памяти и отказы в выделении памяти. Интеллектуальный указатель должен подсчитывать количество ссылок на указанный объект.

На первый взгляд эта задача кажется довольно сложной, особенно если вы не эксперт в C++.

Ответ

Эта головоломка, в которой вас пытаются запутать, предложив поменять свое решение, известна также под именем «Парадокс Монти Холла». Монти Холл был первым ведущим телевизионной игры-шоу «Давайте заключим сделку»

Перед вами три коробки, в одной из которых находится ценный приз, в двух других ничего нет. Вы можете выбрать любую коробку, но вам по-прежнему неизвестно, в какой именно приз. Одну из двух не выбранных вами коробок открывают и показывают, что она пустая. Теперь вы можете или оставить коробку, которую вы первоначально выбрали (оставить), или поменять ее на другую, неоткрытую (заменить). Что вы предпочтете сделать (оставить или заменить)?

Ответ

У вас есть пустое помещение и группа людей снаружи. За один ход вы можете либо позволить одному человеку войти в помещение, либо выпустить из него одного человека. Можете ли вы предложить серию ходов, при которой каждая возможная комбинация людей находится в помещении только один раз?

Нужно время, чтобы понять, чего именно хочет от вас интервьюер. Разобраться в этом помогает простой пример. Скажем, за порогом находятся два человека, Ларри и Сергей. Возможны четыре комбинации их присутствия в комнате, учитывая тот случай, когда в комнате вообще никого нет.

Вот они:

  • В помещении никого нет.
  • В помещении только Ларри.
  • В помещении только Сергей.
  • В помещении Ларри и Сергей.

Вопрос заключается в том, можем ли мы начать с того, что в комнате никого нет, а затем пройти указанную последовательность шагов?

Иными словами, как сгенерировать неповторяющиеся комбинации, меняя только один элемент за раз?

Ответ

Напишите код поиска субматрицы с максимально возможной суммой в матрице N*N, содержащей положительные и отрицательные числа.

Ответ

Сложная задача, требующая умения придумывать алгоритмы.

По условию требуется разработать алгоритм, позволяющий найти k-e число из упорядоченного числового ряда, в разложении элементов которого на простые множители присутствуют только 3, 5 и 7.

Решение с примерами кода на Java есть у нас на сайте.

Решение с примерами кода

Дан список из миллиона слов. Разработайте алгоритм, создающий максимально возможный прямоугольник из букв так, чтобы каждая строка и каждый столбец образовывали слово (при чтении слева направо и сверху вниз). Слова могут выбираться в любом порядке, строки должны быть одинаковой длины, а столбцы — одинаковой высоты.

Ответ

Дан массив с числами типа Integer. Вам нужно написать функцию, которая на входе получит исходный массив, а на выходе вернет массив, в котором каждое значение получено путем произведения всех значений исходного массива с отличным от текущего индексом.

Для ясности приведем пример. Допустим, исходный массив имеет вид:

[1, 7, 3, 4]

Тогда функция должна вернуть:

[84, 12, 28, 21]

Расчет значений происходит следующим образом:

[7*3*4, 1*3*4, 1*7*4, 1*7*3]

Дополнительные условия:

  • Нельзя использовать деление.
  • Функция должна быть с наименьшими затратами памяти и времени выполнения.

Ответ

Задача на умение рассуждать. Конкретный ответ не важен, важно показать как вы мыслите. Представьте, что вам необходимо добраться из точки A в точку B, но вы не знаете, как. Как вы будете действовать?

Ответ

Представьте, что вам дали задание разработать план эвакуации большого города (в классическом варианте — Сан-Франциско). С чего вы начнете?

Ответ

Задача, которую предлагали на собеседованиях в Apple: у вас есть массив с целыми числами, в том числе и отрицательными, вам нужно найти самое большое произведение 3 чисел из этого массива.

Например: у вас есть массив list_of_ints, содержащий числа -10, -10, 1, 3, 2. Функция, которая обрабатывает этот массив, должна вернуть 300, так как -10 * -10 * 3 = 300. Задание нужно выполнить максимально эффективно, не забывая учесть отрицательные числа.

Ответ

Представьте страну, где все родители хотят иметь мальчика. Каждая семья продолжает рожать детей до тех пор, пока у них не появляется мальчик, а затем останавливается. Каково соотношение мальчиков и девочек в этой стране?

Игнорируйте ситуации, когда рождаются двойняшки, тройняшки и так далее, пары, не имеющие детей, и пары, умершие до того, как у них появится мальчик.

Как обычно, предлагаем порассуждать над решением в комментариях. Проверить свой ответ можно на сайте по прикреплённой ссылке, там мы даём наш вариант решения.

Ответ

Задачи на прикидку, то есть подразумевающие приближенное решение — популярный класс задач, которые предлагают на собеседованиях в IT компании. Предлагаем вам несколько таких задач, а также рассказ об общих методах их решения и конкретные советы для собеседований.

Сколько флаконов шампуня производится в мире за год? Ответ

Сколько насечек на ребре четвертака — монеты в 25 центов? Ответ

Сколько будет 2 в 64 степени? Ответ

Сколько туалетной бумаги потребуется, чтобы покрыть ею весь штат? Ответ

Сколько атомов резины стираются с шины автомобильного колеса при каждом его обороте? Ответ

Cколько денег понадобится на мытье всех окон в Сиэтле? Ответ

Также смотрите примеры других задач для самостоятельного решения.

Задача, которую давали на собеседованиях в Apple. От вас требуется написать функцию, которая возвращает максимальную прибыль от одной сделки с одной акцией (сначала покупка, потом продажа). Исходные данные — массив вчерашних котировок stock_prices_yesterday с ценами акций Apple.
Информация о массиве:

  • Индекс равен количеству минут с начала торговой сессии (9:30 утра).
  • Значение в массиве равно стоимости акции в это время.

Например: если акция в 10:00 утра стоила 20 долларов, то
stock_prices_yesterday[30] = 20.

Допустим, имеем некоторые условия:

stock_prices_yesterday = [10, 7, 5, 8, 11, 9]

profit = get_max_profit(stock_prices_yesterday)
#вернет 6 (купили за 5, продали за 11)

Массив может быть любым, хоть за весь день. Нужно написать функцию get_max_profit как можно эффективнее — с наименьшими затратами времени выполнения и памяти.

Ответ

Задача про слияние промежутков в календаре.

Предположим, компания, в которой вы работаете, разрабатывает электронный календарь. В календаре есть функция, показывающая, когда различные команды программистов будут заняты на какой-либо встрече.

Те периоды, когда команда занята, на календаре отмечены как диапазоны времени, например, с 10:00 до 12:30 или с 12:30 до 13:00. В разрабатываемой программе промежуток времени представлен в виде кортежей из двух целых чисел. Число означает номер 30-минутного блока, который идет после 9:00 утра. Например, кортеж (2, 4) означает диапазон с 10:00 до 11:00, а (0, 1) — это промежуток 9:00-9:30.

Вам нужно написать функцию, которая должна упростить вывод информации таким образом, что если команда занята в промежутках с 10:00 до 12:30 и с 12:30 до 13:00, то это отображалось как 10:00‒13:00. Например: на входе вашей функции неупорядоченный массив из кортежей [(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)], а на выходе вы должны получить упорядоченный массив [(0, 1), (3, 8), (9, 12)].

В будущем планируется внести изменения в программу, где вместо 30-минутных блоков будут минутные, как это реализовано в представлении Unix-времени. С учетом этого изменения нужно, чтобы ваша функция уже сейчас могла работать с большими числами. Еще не забудьте, что кортеж — это такой тип данных, в котором содержимое переменной невозможно изменять после ее создания.

Ответ

Задача, которую давали на собеседованиях в Apple. Представьте, что вы получили работу кассира в магазине. Ваш босс случайно выяснил, что вы обладаете навыками программиста, и захотел, чтобы вы помогли ему написать программу.

Входные данные:

  1. Указанная сумма денег.
  2. Массив со всеми доступными номиналами монет.

Нужно написать функцию, которая на выходе выдаст количество всех возможных способов получить указанную сумму денег при помощи различных доступных номиналов монет. Например, если вам нужно получить 4 цента из монет номиналами 1, 2 и 3 цента, то функция вернет 4 — именно столько есть возможных комбинаций из чисел 1, 2 и 3, чтобы получить в сумме 4:

  1. 1, 1, 1, 1.
  2. 1, 1, 2.
  3. 1, 3.
  4. 2, 2.

Ответ

Эту задачу когда-то давали в Google.

Вам нужно подняться по лестнице. За один раз можно подняться на одну или две ступеньки. Сколько существует способов добраться до N-й ступеньки?

Ответ

Эту задачу задавали на собеседовании в Twitter.
Рассмотрим следующую картинку:

задача про стены и дождь, собеседование в Twitter

На этой картинке изображены стены различной высоты в некотором плоском мире. Картинка представлена массивом целых чисел, где индекс — это точка на оси X, а значение каждого индекса — это высота стены (значение по оси Y). Картинке выше соответствует массив [2, 5, 1, 2, 3, 4, 7, 7, 6].

Теперь представьте, что начался дождь, который не прекращается и поливает стены сверху равномерным потоком. Сколько воды соберется в «лужах» между стенами?

1-MKQZbWOdLPK-DD10Y48fkQ

задача про стены и дождь, собеседование в Twitter

Единицей объема воды считаем квадратный блок 1×1. На картинке выше всё, что расположено слева от точки 1, выплескивается. Вода справа от точки 7 также прольется. У нас остается лужа между 1 и 6 — таким образом, получившийся объем воды равен 10.

Ответ

Задача про бесконечный поезд.

Представьте себе замкнутую по окружности железную дорогу. По ней едет поезд, последний вагон которого скреплён с первым так, что внутри можно свободно перемещаться между вагонами. Вы оказались в одном случайном вагоне и ваша задача — подсчитать их общее количество. В каждом вагоне можно включать или выключать свет, но начальное положение переключателей случайное и заранее неизвестно.

Все вагоны внутри выглядят строго одинаково, окна закрыты так, что невозможно посмотреть наружу, движение поезда равномерное. Помечать вагоны как-либо, кроме включения или выключения света, нельзя. Количество вагонов конечно (не верьте названию задачи).

Ответ

Вы стоите перед закрытой комнатой, в которой есть три лампочки. На стене перед вами три переключателя: каждый из которых включает или выключает одну из лампочек. Вам нужно узнать, какой переключатель к какой лампочке относится, при условии, что зайти в комнату вы можете только один раз.

Расположение переключателей случайное, порядок подключения заранее неизвестен. Зайдя в комнату, можно делать с лампочками всё, что угодно, но уже нельзя вернуться к переключателям. Изначально все лампы выключены.

Если вы хотите решить задачу самостоятельно, но в голову ничего не приходит, можете воспользоваться нашей подсказкой.

У лампочек при начальных условиях есть только два состояния: горит или не горит. Понятно, что этого недостаточно, чтобы разделить их на три группы. Вам нужно придумать какие-то ещё состояния лампочек и способ их добиться переключателями.

Или смотрите сразу ответ

Классическая задача. Найдите в данной вам строке максимальную по длине подстроку, которая является палиндромом (то есть читается слева направо и справа налево одинаково). Предложите как можно более эффективный алгоритм.

Ответ

Реализуйте функцию извлечения квадратного корня, не пользуясь встроенными в язык средствами нахождения корня и возведения в степень.

Ответ

В этой задаче вам необходимо реализовать функцию, которая бы проверяла число на четность, используя только битовые операции AND, OR, NOT.

Ответ

На прямой даны N отрезков (в реальной жизни это могут быть промежутки времени, например), которые заданы координатами их левого и правого конца. Для каждого данного отрезка необходимо узнать, сколько из данных отрезков полностью находятся в нем. Один отрезок полностью содержится во втором, если левый конец первого отрезка находится правее левого конца второго отрезка, а правый конец первого находится левее правого конца второго. Предложите как можно более эффективный способ решения этой задачи. Гарантируется, что все концы данных отрезков различны.

Если вы придумали решение, то написать и проверить его вы можете здесь, на codeforces.

Сможете ли вы решить эффективно данную задачу в случае, если концы отрезков могут совпадать?

Ответ

Придумать алгоритм, определяющий, все ли символы в строке встречаются один раз.
При выполнении этого задания нельзя использовать дополнительные структуры данных.
Ответ

В массиве случайных чисел A[0…n-1] задан один «волшебный» индекс: такой, что A[i] = i. Значения элементов в массиве повторяться не могут. Учитывая, что массив отсортирован по значениям в порядке возрастания, напишите метод, который определит этот «волшебный» индекс, если он существует в массиве A. Если элемента в массиве нет, верните любое отрицательное число.

Как изменится решение, если известно, что таких индексов в массиве несколько?

Ответ

Как можно узнать количество дней в месяце, зная его номер? Другими словами, опишите, как получить функцию f(x), которая бы давала следующий список значений:

В качестве аргумента мы получаем только номер месяца, т.е. мы не учитываем високосные года, и f(2) = 28.

Ответ

Задачка для питонистов: нужно перебрать все пары символов в строке, и остановиться при нахождении двух одинаковых символов.

Решение достаточно очевидное, но возникает вопрос:

s = "какая-то строка"
for i in range(len(s)):
    for j in range(i+1, len(s)):
        if s[i] == s[j]:
            print(i, j)
            break   # Как выйти сразу из двух циклов?

Если бы мы программировали, например, на Java, то мы могли бы воспользоваться механизмом меток:

outterLoop: for(int i=0; i<n; i++){
    for(int j=i; j<n; j++){
        if(/*something*/){
            break outterLoop;
        }
    }
}

Однако в Python такого механизма нет. Требуется предложить наиболее удобное в использовании и читаемое решение.

Ответ

Написать код, который проверяет, пересекутся ли две заданные прямые, лежащие в одной плоскости.
Предположим, что нам необходимо разработать структуру данных для хранения информации о прямой, и будем считать, что если две линии совпадают, то они пересекаются.

Вероятно, из школьного курса вы помните, что если две линии, лежащие в одной плоскости, не параллельны, то они пересекаются. Таким образом, чтобы проверить, пересекаются ли две линии, достаточно проверить, различаются ли их наклоны и не совпадают ли их сдвиги.

Ответ

Классическая задача: посчитать N-е число последовательности, в которой каждый элемент равен сумме двух предыдущих. Такая последовательность называется последовательностью Фибоначчи: 1, 1, 2, 3, 5, 8…

Очень часто на разнообразных олимпиадах попадаются задачи вроде этой, которые, как думается на первый взгляд, можно решить с помощью простого перебора. Но если мы подсчитаем количество возможных вариантов, то сразу убедимся в неэффективности такого подхода: например, простая рекурсивная функция, приведенная ниже, будет потреблять существенные ресурсы уже на 30-ом числе Фибоначчи, тогда как на олимпиадах время решения часто ограничено 1-5 секундами.

int fibo(int n)
{
    if (n == 1 || n == 2) {
        return 1;
    } else {
        return fibo(n - 1) + fibo(n - 2);
    }
}

Придумайте, как найти N’е число Фибоначчи за приемлемое время.

Ответ

Чтобы разобраться в теме, рекомендуем почитать нашу статью про динамическое программирование для начинающих.

Одна из самых известных задач Интернета, будоражащая многие светлые умы человечества.

Самолет стоит на взлетной полосе с подвижным покрытием типа транспортера. Покрытие может двигаться против направления взлета самолета, то есть ему навстречу. Транспортер автоматически регулирует свою скорость таким образом, чтобы самолет оставался неподвижным. Вопрос: сможет ли самолет в таких условиях взлететь?

задача взлетит ли самолет

Здесь нужно отметить, что при ближайшем рассмотрении условие задачи оказывается некорректным. Во-первых, шасси вращаются с угловой скоростью, а лента с линейной, поэтому их сравнение некорректно. Во-вторых, если принять, что угловая скорость колес транспортера равна угловой скорости колес самолета и их диаметры равны, то задача сводится к неподвижному относительно земли самолету. Но будем исходить из того, что транспортер просто движется так, чтобы не дать едущему по транспортеру самолету перемещаться относительно земли. Конечно, с точки зрения физики задача не совсем корректна и по другим причинам, но можно попробовать решить ее эмпирически.

Ответ

Задача на перегрузку функций в C++, которая может оказаться сложнее, чем выглядит.

Предположим, у нас есть два класса:

class Parent {
  public:
  virtual void print() { 
    std::cout << "Родительский класс" << std::endl; 
  }
};

class Derived : public Parent {
  public:
  virtual void print(int x) { 
    std::cout << "Производный класс" << std::endl;
  }     
};

Что выведут два следующих куска кода и почему?

int main() {
  Derived *derived = new Derived;
  derived -> print();
  return 0;
}  

int main() {
  Parent *derived = new Derived;
  derived -> print();
  return 0;
}

Ответ

Рассмотрим ситуацию, когда три работника хотят вычислить свою среднюю зарплату при условии, что каждый знает свою зарплату, но не может сообщить ее другому напрямую. Обмен информации между людьми возможен, но передаваемые друг другу сообщения не должны содержать какую-либо конкретную информацию об уровне зарплат. Как это сделать?

Ответ

Пусть у нас есть массив положительных чисел, в котором все числа, кроме трех, встречаются по 2 раза, а эти три числа отличны от всех остальных и встречается каждое ровно по одному разу. Нужно найти эти три числа. Числа помещаются в 32-битный целочисленный тип.

Ответ

Положим, у нас есть некоторая конечная последовательность чисел и мы имеем итератор, указывающий на первый элемент. Мы можем при помощи итератора посмотреть значение текущего элемента и перейти к следующему элементу. Требуется построить такой алгоритм выбора случайного элемента из этой последовательности, чтобы каждый элемент мог оказаться выбранным с равной вероятностью.

Ограничения: мы можем использовать O(1) дополнительной памяти и не можем создавать новый итератор. Можно пользоваться функцией генерации случайного числа от [0;1).

Ответ

Известная задача с IT-собеседований с несколькими вариантами решения: как правильно реализовать обмен значений переменных?

a = b; 
b = a;

Если вы попытаетесь выполнить обмен значений этим способом, то увидите, что теперь в обеих переменных хранится значение переменной b. Происходит это ввиду построчного выполнения кода. Первая операция присваивания сохраняет значение переменной b в переменную a. Затем вторая — новое значение a в b, иными словами значение b в b. Таким образом, мы полностью теряем содержание контейнера a.

Ответ

На одной стороне реки находятся три человека и три льва. Все они должны оказаться на другом берегу реки. Есть лишь одна лодка, в которой могут поместиться лишь два живых существа одновременно (человека или льва). Вы не можете оставлять на том или другом берегу реки больше львов, чем людей, так как в этом случае животные съедят людей, оставшихся в меньшинстве. Как вы переправите всех через реку?

Ответ

Если бы вы получили стопку монет достоинством в один пенс каждая и высотой с Эмпайр-стейт-билдинг, поместились бы все эти деньги в одном помещении?

Сперва может показаться, что это одна из тех головоломок, в которых предполагается оценить какое-то абсурдное число. Но на самом деле это не так, подумайте хорошенько.

Ответ

Также рекомендуем по теме:

  • 28 cайтов с задачами по программированию
  • Десять наиболее частых ошибок программистов при подготовке к собеседованию
  • Подборка полезных алгоритмов для собеседований: задачи на строки
  • 14 алгоритмических задач с разбором решений по итогам «Технокубка» 2017
  • Олимпиада «Технокубок»: разбор задач финального раунда
  • Разбираем решения задач предварительного тура Russian Code Cup

Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.

Я довольно часто общаюсь с начинающими разработчиками, помогаю им на различных площадках и в чатах. Отвечаю на вопросы как общего характера, так и связанные с какой-либо технологией или отладкой кода. Также я иногда провожу код-ревью проектов, над которыми работают ребята — это бывают как проекты на Хекслете, открытые (опенсорсные) проекты, так и тестовые задания самого разного размера.

Я помню, как сам делал самое первое тестовое задание. Оно было с одной стороны простым, но с другой — сложным, нужно было сделать на PHP без фреймворков небольшое приложение для добавления статей и загрузки древовидных комментариев. Подобное задание можно сделать не только на PHP, но и на любом языке для веба — Go, Python, Ruby, Java, NodeJS.

Несмотря на то, что стек технологий разнится, ошибки могут быть типовыми:

  1. Код не запускается или не выполняет поставленную задачу
  2. Отсутствует описание (README). Соответственно, нет инструкций по запуску
  3. Код не соответствует принятым стандартам кодирования и best practices
  4. Задание было прислано в архиве или Google Docs, то есть не использовалась система контроля версий, например, Git.

В тексте я поделюсь советами, которые помогут улучшить ваше тестовое задание, узнать о существовании полезных инструментов и развить навыки разработки и развертывания приложения. Это советы абсолютно универсальны — их можно применить не только к тестовому заданию, но и вообще к любому вашему проекту на Github.

Описание проекта и общее оформление

Добавьте описание того, что делает ваш проект, даже если это ToDo App — приложение для ведения задач. Опишите, какие используются технологии, версии языка и библиотек. Укажите требования к операционной системе и пакетам, которые необходимо установить. Опишите команды, которые могут использоваться для развертывания приложения, чтобы его можно было разрабатывать или демонстрировать.

Если у приложения есть рабочая демонстрация, укажите на нее ссылку. Это может быть ссылка на GitHub Pages, Heroku или ваш домен и сервер, где приложение развернуто и его можно посмотреть.

Проверьте, что в тексте нет ошибок. Не все владеют русским или английским языком идеально. Но даже текстовые редакторы кода (например, VSCode) подсвечивают все опечатки.

Описание проекта стоит делать либо на английском языке, либо на том языке, который используется в компании и на котором вы получили тестовое задание. Если это просто пет-проект для тренировки, который выложен на GitHub, старайтесь использовать английский язык. Возможно, если вы находитесь в поиске работы, с вами даже свяжется зарубежная компания. Для перевода текстов я обычно использую Deepl.com — для перевода он использует машинное обучение, поэтому часто там переводы лучше, чем в Google Translate.

Если вы делаете приложение с веб-интерфейсом (например, сайт, где можно публиковать новости), используйте готовое решение, не занимайтесь версткой и стилизацией самостоятельно. Для таких целей можно использовать фреймворк Bootstrap.

Когда вы работаете над тестовым заданием, не забудьте приложить текст задания в README или отдельно в проект. Ревьюер может его просто не иметь при себе, или забыть какие-то мелочи. Также вы сможете это задание использовать в вашем портфолио, в таком случае текст задания будет служить описанием проекта.

Например, так выглядит репозиторий без описания:

А так выглядит репозиторий проекта с подробным README:

Общая работоспособность проекта

Если вы делаете тестовое задание, обязательно сверяйтесь с условиям. Если их нет, стоит их уточнить. Спросите себя — достигнута ли поставленная цель? Нажимаются ли кнопки? Работает ли регистрация? Сохраняются ли данные? Об этом часто забывают из-за неопытности. Вы можете сфокусироваться на чем-то одном и забыть про остальные части приложения.

Очень обидно, когда твою работу не примут из-за того, что ты где-то не поставил скобку или опечатался. Про тесты я расскажу дальше, но помните — ваше решение должно быть рабочим. Да, бывают моменты, когда просят сделать не рабочее решение, а абстрактное. Например, описать интерфейсы классов, использовать заглушки, но обычно это указано в ТЗ.

Качество кода, стандарты кодирования, линтеры

Есть теория, которая называется «Теория разбитых окон». В ней говорится, что «Если в здании разбито одно стекло и никто его не меняет, то через некоторое время в этом здании не останется ни одного целого окна». Такой подход актуален и для кода. Если мы начинаем забивать на соблюдение стиля кода, то в итоге начинаем писать как попало — и перестаем обращать внимание на весь код вообще, различные подходы и здравый смысл.

Линтеры — это инструменты (скрипты), которые проверяют код на соответствие настроенным стандартам. Они нужны для того, чтобы было единство кода как внутри проекта, так и между множеством разработчиков. То есть линтеры нужны для того, чтобы другой разработчик мог с легкостью писать код и не думать о том, что ему использовать — табы или пробелы.

Сравните. Оба примеры написаны на PHP с использованием условной конструкции, но в одном случае стандарты игнорируются:


if ($a === $b) 
{
  bar();
} 
elseif ($a > $b) {
  $foo->bar($arg1);} else 
{
    BazClass::bar($arg2, $arg3);
}

А в следующем случае разработчик использует линтер для соблюдения стандартов:

if ($a === $b) {
    bar();
} elseif ($a > $b) {
    $foo->bar($arg1);
} else {
    BazClass::bar($arg2, $arg3);
}

Чтобы разработчики не ругались о том, какое форматирование использовать, они договариваются о едином стандарте для кода. В каждом языке есть общепринятые стандарты. Иногда стандартов может быть несколько. Еще реже бывают отдельные стандарты внутри проекта или внутри компании. В PHP общепринятый стандарт — PSR, для JS чаще всего используется стандарт от Airbnb.

Современные редакторы позволяют настроить проверку и исправление ошибок как при редактировании кода, так и по специальной команде, например, по горячей клавише. При необходимости правила линтера могут изменяться — например, можно не проверять определенные файлы. Правила линтера могут даже расширяться — например, сортировать импорты, либо указывать возвращаемый тип у функции. Обычно использование линтера — это санитарное правило, как мытье рук перед едой.

На Хекслете есть проекты — практические задания разной степени сложности, где нужно сделать свое приложение по техническому заданию. Во время код-ревью этих проектов используется вот такой порядок проверки:

Проверка кода идет по пунктам указанным ниже. Если на верхнем уровне есть серьезные проблемы, то проверка останавливается до исправления.

  1. Конфигурация (линтеры, запуск тестов, CI).
  2. Внешний вид и общая работоспособность.
  3. Тесты.
  4. Авторизация.
  5. Правильное использование роутинга (имена, именованные маршруты).
  6. Оформление шаблонов.
  7. Оформление моделей.
  8. Оформление обработчиков.

Если игнорируются ошибки линтера на самом верхнем уровне, код не проходит ревью, а возвращается студенту с просьбой исправить замечания. Обычно линтер становится частью CI/CD (про это ниже), поэтому если при написании вы забудете проверить свой код, это сделает скрипт.

Кроме линтера можно использовать и различные онлайн-инструменты для проверки качества кода. В проектах Хекслета используется CodeClimate — этот сервис анализирует код и может подсветить моменты, которые стоит поправить. Например, глубокую вложенность с условиями и циклами.

Читайте также:
Как пройти собеседование на тестировщика: все этапы и вопросы

Автоматические тесты

В современной разработке от тестирования никуда не деться. Умение писать тесты и тестируемый код сейчас встречается практически в каждой вакансии. И сама культура написания тестов существует уже довольно давно. Если вы откроете любую хорошую книгу по разработке, наверняка найдете там главу или целый раздел, посвященный написанию тестов.

Грамотные тесты могут ускорять разработку, плохие, неудобные или медленные тесты — наоборот. Их не хочется запускать, они могут часто ломаться от каждого изменения или выполняться несколько часов.

Современные фреймворки и библиотеки помогают писать простые и легкие тесты. Например, во фреймворке Laravel есть множество инструментов для этого: утверждения (assertions) для проверки данных, стабы для внешних запросов, генерация тестовых данных.

Для JS используется jest и обертки-библиотеки, которые помогают писать тесты. Для фронтенда есть библиотека testing-library — ее можно использовать с любым популярным фреймворком React/Angular/Vue. Для PHP повсеместно используется PHPUnit. Обязательно изучите эти инструменты и попробуйте написать парочку тестов.

Старайтесь не писать низкоуровневые тесты. Вы могли видеть пирамиду тестирования, где на нижнем уровне находятся юнит-тесты, а на самом верху — интеграционные. Это довольно условное деление, ведь что-то может быть отдельным компонентом, а что-то — целой системой. Все зависит от того, как посмотреть.

Большие фреймворки (Laravel, Symfony) уже обладают удобными инструментами для тестирования. Вы сможете с легкостью написать один функциональный тест, который будет проверять основную логику приложения. Один высокоуровневый тест может заменить десяток низкоуровневых. Если тесты проходят быстро, это удобно.

Модульные тесты полезны там, где нужно изменить какой-то кусок кода со сложной логикой, если в нем нет побочных эффектов — например, вызова внешнего сервиса или обращения к базе. Но если у вас уже есть верхнеуровневый тест, который покрывает этот кусок кода, смысла в модульном тесте по большому счету нет.

По теме тестов есть полезная статья «Бережливое тестирование, или Почему модульные тесты хуже, чем вы думаете».

CI/CD, автоматизация, деплой

Теперь, когда вы стали использовать линтеры и тесты, вы можете заставить их работать и помогать вам на регулярной основе.

Что такое CI/CD? Если коротко, в процесс выкладки кода (например, обычный git push на GitHub) встраивается автоматизация и различные проверки. Как это может выглядеть? Вы разрабатываете что-то у себя, пишете код. Проверили — все работает. Делаете коммит, пуш, код уходит на GitHub. Дальше там могут происходить различные действия в зависимости от того, что вы настроили.

Самый простой вариант CI/CD — запускается сборка, ставятся зависимости, запускаются линтеры, тесты. Более сложный вариант — происходит деплой (публикация) вашего приложения, линковка, создание нового сервера.

Читайте также:
Как разработчику правильно описать хард-скиллы в своем резюме

Если ваш проект выложен на GitHub, вы можете воспользоваться бесплатным решением платформы — Github Actions. Так как GitHub — это про сообщество и опенсорс, можно переиспользовать скрипты-экшены других разработчиков. Например, в PHP можно использовать экшен, который проверяет зависимости приложения на уязвимости.

Конечно же, можно определять и свои команды. Из этих команд вы собираете цепочку, в которой они выполняются последовательно друг за другом. Например:

  1. Скачать исходный код
  2. Установить зависимости
  3. Подготовить проект (например, создать необходимые переменные или миграции)
  4. Запустить линтер
  5. Запустить тесты.

Все действия будут совершаться без участия программиста и помогут отследить ошибку, пока ведется разработка.

Вернемся к тестовому заданию со статьями. Напомню, что нужно сделать приложение, в котором можно создать статью и оставить комментарии. При этом комментарии должны быть в виде дерева, как на Хабре. Вы знаете, что ваше приложение работает 100%, ведь вы даже написали тесты. Будет ли проверяющий запускать код? Допустим. Но что, если нужно проверить аналогичные проекты у 20 человек? Тогда вряд ли он это сделает. Даже если скачать и развернуть ваше приложение займет две минуты, то на всех уйдет минут 40. При этом каждому нужно посмотреть код, оценить его, дать фидбек.

Если вы выложите ваше приложение куда-то, ревьювер сможет подергать методы или прожать кнопки. А также наверняка оценит то, что вы сэкономили ему время.

Для этого можно использовать различные облачные сервисы. Для бэкенда можно использовать Heroku. Он интегрируется с GitHub и позволяет деплоить приложение по команде git push. Особенность Heroku в том, что он не обладает своей файловой системой, поэтому там нельзя хранить ничего, кроме кода, но можно подключить различные хранилища, например, базу данных. Есть бесплатные тарифы, которые идеально подойдут для выполнения такой задачи.

При этом, если вы используете какие-то проверки — например, линтеры и тесты, то код не будет деплоиться Heroku, если они будут провалены.

Для фронтенда можно использовать Vercel, Netlify, Github Pages. Кроме того, там тоже можно настроить сборку приложения и автоматизировать деплой.

Читайте также:
Не бояться, решать задачи и проверить звук в Zoom: Как джуниор-разработчику подготовиться к собеседованию

Система контроля версий (VCS), Git

Думаю, вы уже догадались, что нужно использовать Git. Именно вокруг него строятся различные интеграции и автоматизации. Прошли те времена, когда разработчики хранили на своем жестком диске копии файлов index.php, index_backup.php, index2.php на случай, если что-то пойдет не так.

Git позволяет работать одновременно над разными кусками кода, сравнивать их между собой. Хранит в себе историю изменений — кто, когда и что поменял. Использование этого инструмента — это еще одна санитарная норма в современной разработке.

Историю коммитов можно использовать для анализа того, как развивалось приложение, какие решения принимались, оценить навык использования инструмента. Иногда встречается такое, что в проекте за все время существования есть всего один коммит. Обычно я делаю вывод, что разработчик не любит пользоваться этим инструментом и проверяет у себя локально, отправляя в удаленный репозиторий готовое решение.

Старайтесь использовать понятные, краткие описания к коммитам. Желательно на английском языке или хотя бы на том, который принят в компании, для которой вы выполняете задание.

Если есть сложности в работе с Git — пройдите наш курс. Помните, что это теория, которую стоит закреплять на практике.

Я не упомянул здесь Docker. Если вы умеете им пользоваться, это круто. Оформите конфиг и команды для запуска вашего приложения в Docker. Он позволяет упаковать приложение в изолированное окружение (например, настройки веб-сервера, специфические системные утилиты и пакеты), повысить переносимость, а инфраструктура приложения станет иммутабельной.

Архитектура, шаблоны, построение кода

Хаха, а тут советов нет. Выдумывайте сами.

Нет, на самом деле. Задача тестового задания — проверить ваши знания. Конкретные штуки. Например, как вы применяете паттерны, если они нужны. Как структурируете код, какие абстракции выделяете. Тяжело давать советы, которые актуальны для всех. Просто пишите понятный код. Все будет зависеть от вашего опыта и знаний.

В вакансиях вы часто можете увидеть требование «писать понятный, чистый код». На самом деле это тяжело делать, если нет опыта. Поэтому просто пишите код, пишите код, пишите код.

Читайте книги, смотрите доклады, анализируйте код других разработчиков. Старайтесь понять, почему сделано именно так. Анализируйте популярные решения, почему они так реализованы.

Подходы и решения могут быть вообще разными в разных языках — код одного и того же веб-приложения на PHP и Ruby, Python, JS будет выглядеть по-разному. Некоторые решения будут просто не нужны в рамках других языков. Например, паттерны — их придумывают из-за несовершенства и ограничений языков.

Руководствуйтесь здравым смыслом. Например, если у вас есть шаблон странички и какие-то компоненты, будет некорректно обращаться к базе данных из шаблона. Кроме того, имена переменных должны быть понятными — избегайте ненужных сокращений, лишнего контекста. Если у вас какие-то данные или процедуры дублируются, значит, что это какая-то абстракция — и ее стоит выделить отдельно.

Если начитаться про паттерны, SOLID и другие принципы, можно легко уйти в оверинжиниринг (придумывать функционал на будущее). Старайтесь сделать свое решение простым и понятным (KISS) — ведь скорее всего то, что вы заходите добавить, вам никогда не понадобится (YAGNI). Готовьтесь обосновывать те решения, которые приняли в коде.

Программирование — это творческий процесс, который контролируете только вы. Практикуйтесь.

Читайте также:
Как решить задачу, если непонятно, с чего начать: советы от Хекслета

Работа над заданием, сбор фидбека

Когда вам предлагают сделать тестовое задание, обычно сразу же указывают дедлайн. В других случаях компания может спросить у разработчика, сколько времени у него оно займет. Например, справитесь ли вы за неделю, либо вам понадобится всего два дня.

Без опыта невозможно дать грамотную оценку трудозатрат. Проблема с оценкой времени есть даже у опытных разработчиков. Поэтому прикиньте по времени, сколько вы будете работать над задачей, и возьмите немного времени с запасом.

Если возникают ситуации, когда вам непонятна формулировка задания или требования, лучше спросить, а не играть в угадайку. Потому что задания могут быть действительно неверно сформулированы, либо даже сделаны таким образом, чтобы побудить вас задавать вопросы.

Я слышал о ситуациях, когда разработчику было непонятно тестовое задание и он задавал по нему уточняющие вопросы. На это заказчик (работодатель) говорил, мол, вы не слишком самостоятельны, раз задаете много вопросов. Кажется, что это не очень правильно и нужно дважды подумать, прежде чем идти в такую компанию.

Если есть вопросы, спрашивайте. Если вы задерживаетесь с заданием, сообщайте об этом. Возможно, можно будет отправить задание попозже или частично завершенное. Важно иметь обратную связь, а не пропадать из поля зрения, если что-то пошло не так. Вопросы, связанные непосредственно с разработкой, лучше не спрашивать — типа «У меня проблема с такой-то библиотекой, которую вы сказали использовать, поможете?». Ведь то, как вы разберетесь с технологией, тоже является частью тестового задания.

Можно сразу же поделиться ссылкой на репозиторий, чтобы ревьювер мог смотреть за ходом разработки.

Где взять тестовые задания?

У Хекслета есть репозиторий, в котором сообщество делится тестовыми заданиями. Сюда присылают ссылки студенты, сторонние разработчики и даже сами компании. Задания самого разного уровня, на любой стек и уровень.

Как учиться писать более лучший код

Практика, практика и еще раз практика. Как говорилось выше — пишите больше кода, читайте книги, изучайте проекты. У Хекслета есть множество проектов, в которых можно принять участие. За этими проектами следят и, как правило, хорошие практики переносятся из одного проекта в другой. Даже стек особо не важен. Например, в каждом проекте используется Makefile и есть подробное ридми для описания инструкций по работе с проектом. Вы можете подглядеть, как писать тесты, как работать с популярным фреймворком (Laravel, Ruby On Rails) и даже как создать инфраструктуру с помощью Terraform и Ansible (вряд ли это будет в вашем тестовом, ну а вдруг).

А можно не делать тестовое?

На самом деле тестовое задание предлагается далеко не всем. Чаще всего их дают начинающим разработчикам или тем, у кого нет портфолио. В резюме соискатели пишут, что владеют определенными технологиями, и это нужно проверить. Бывает, что у компании специфический стек (типа Clojure), но у кандидатов нет опыта по этой технологии. Тогда могут найти опытного человека (который уже поработал программистом), но без опыта с нужной в компании технологией.

По моему опыту, чем больше у разработчика полезного кода на Github, тем выше вероятность, что ему не придется делать тестовое задание. Например, проекты Хекслета, открытые проекты, пет-проекты или тестовые задания. Например, я делал тестовое один раз, когда у меня не было даже проектов Хекслета. Потом это же тестовое пригодилось в поиске следующей работы, и в трудоустройстве в другую компанию.

Читайте также:
Как понять, что перед вами плохой разработчик

Итого

В этой статье мне хотелось рассказать вам про технологии, подходы и практики, которые можно использовать при работе над тестовым заданием.

Кто-то скажет, что не нужно насчет всего этого заморачиваться. Но я постоянно вижу, что кандидаты выполняют тестовое задание, но его толком не проверяют просто потому, что оно оформлено криво.

Часть перечисленных практик уже являются стандартами разработки. Попробуете один-два раза и поймете, насколько круто их использовать. Вы покажете, что знакомы с кучей технологий хотя бы поверхностно, и что это для вас не пустой звук. Тогда с вас останется просто писать грамотный код.

Полезные ссылки

Git

GitHub — git-хостинг и сообщество разработчиков

Git How To: курс обучения Git на русском

Стиль именования коммитов / Хабр

Как следует писать комментарии к коммитам

Автоматизация, CI/CD, деплой

Как и для чего использовать Docker

Вебинар: Stateful vs. Stateless

Никита Соболев — Автоматизируем все с GitHub Actions. Доклад, рассказывающий, что такое Github Actions, с примерами использования

Code Climate — платформа для статистического анализа и поиска проблемных мест. Также позволяет оценивать покрытие кода с помощью скрипта (показывает бейджик с процентом покрытия тестами)

Eslint — линтер для Javascript

airbnb style guide — популярный стайлгайд для Javascript

Jest — фреймворк тестирования для Javascript

Testing-library — библиотека для тестирования фронтенда в Javascript

PHPUnit — фреймворк для тестирования в PHP

PHP_CodeSniffer — популярный линтер для PHP

PSR-12 — современные стандарты кодирования для PHP

Vercel и Netlify — платформы для развертывания приложения (статика, фронтенд)

Heroku — платформа для облачного развертывания приложения, подходит для бэкенд-приложений

Дополнительно

Как быстро стоит делать тестовое

Рефакторинг и Паттерны проектирования

Продуманная оптимизация

The Twelve-Factor App (Русский перевод)

Список тестовых заданий для прокачки

Книги

Совершенный код

Видео

Доклады по ментальному программированию. Про важность нейминга и семантичности кода

  • Часть 1
  • Часть 2

Доклад «Снесите это немедленно»

Как писать качественный и понятный код? Чистые функции

Начинаем писать тесты (правильно)

Никогда не останавливайтесь:
В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях

В этой статье я расскажу о задачах и вопросах, которые ждут программистов на собеседовании при приёме на работу.


Интервьюеры не отличаются оригинальностью, и один и тот же вопрос можно встретить на 3-5 разных собеседованиях. Но даже опытные программисты, оказываясь в стрессовой ситуации, нередко теряются и не могут найти ответ на довольно простые вопросы. Предлагаем заранее потренироваться, проверить свои знания, а заодно посмотреть на любимые вопросы интервьюеров. Не исключено, что именно на них вам предстоит отвечать на следующем собеседовании.

Структуры данных и вопросы об алгоритмах – основная часть любого собеседования для программистов вне зависимости от их специализации.

1. Как найти средний элемент в LinkedList за один проход?

Это один из самых популярных вопросов на собеседованиях. Его используют даже в телефонных интервью, чтобы быстро определить общий уровень знаний кандидата и оценить его способность быстро решать нестандартные задачи.

Все программисты знают, что средний элемент в LinkedList несложно найти, определив длину списка, последовательно пройдя все его узлы, пока не дойдёшь до NULL в первом проходе. А затем, пройдя половину из них во втором проходе. Когда же их просят решить эту задачу за один проход, многие теряются.

Большинство задач, поставленных на собеседовании, имеет довольно простое решение, и сидя в спокойной обстановке, Вы без особого труда найдёте его сами.

Решение

В этой задаче достаточно ввести два указателя. Первый будет увеличиваться при прохождении одного узла списка, второй – при прохождении двух узлов. В момент, когда второй указатель дойдёт до конца списка (наткнётся на NULL), первый будет указывать на середину списка.

Успешно справились с этим вопросом? Получите следующий.

Исходный код решения

Решение

public class Central {	 	 
 	public static void main(String args[]) {	 	 
 		LinkedList linkedList = new LinkedList();	 	 
		LinkedList.Node head = linkedList.head();	 	 
		linkedList.add( new LinkedList.Node("1"));	 	 
		linkedList.add( new LinkedList.Node("2"));	 	 
		linkedList.add( new LinkedList.Node("3"));	 	 
		linkedList.add( new LinkedList.Node("4"));	 	 
		linkedList.add( new LinkedList.Node("5"));	 	 
		linkedList.add( new LinkedList.Node("6"));	 	 
		linkedList.add( new LinkedList.Node("7"));	 	 
		linkedList.add( new LinkedList.Node("8"));	 	 
		linkedList.add( new LinkedList.Node("9"));	 	 
		linkedList.add( new LinkedList.Node("10"));	 	 
 		LinkedList.Node current = head;	 	 
 		int length = 0;	 	 
 		LinkedList.Node middle = head;	 	 
 		while(current.next() != null){	 	 
 			length++;	 	 
 			if(length%2 ==0){	 	 
 				middle = middle.next();	 	 
 			}	 	 
 			current = current.next();	 	 
 		}	 	 
 		if(length%2 == 1){	 	 
 			middle = middle.next();	 	 
 		}	 	 
 		System.out.println("length of LinkedList: " + length);	 	 
 		System.out.println("middle element of LinkedList : " + middle);	 
	}	 	 
}	 	 
class LinkedList{	 	 
 	private Node head;	 	 
	private Node tail;	 	 
	public LinkedList(){	 	 
	this.head = new Node("head");	 	 
		tail = head;	 	 
	}	 	 
 	public Node head(){	 	 
 		return head;	 	 
 	}	 	 
 	public void add(Node node){	 	 
 		tail.next = node;	 	 
 		tail = node;	 	 
 	}	 	 
 	public static class Node{	 	 
 		private Node next;	 	 
 		private String data;	 	 
 		public Node(String data){	 	 
 			this.data = data;	 	 
		}	 	 
	 	public String data() {	 	 
			 return data;	 	 
		}	 	 
 		public void setData(String data) {	 	 
 			this.data = data;	 	 
 		}	 	 
 		public Node next() {	 	 
 			return next;	 	 
 		}	 	 
 		public void setNext(Node next) {	 	 
 			this.next = next;	 	 
 		}	 	 
 		public String toString(){	 	 
 			return this.data;	 	 
 		}	 	 
 	}	 	 
}

2. А если LinkedList зациклен?

Решение

Если в списке есть цикл, то в какой-то момент оба указателя будут показывать на один и тот же узел списка.

3. Этот вопрос может модифицироваться в «Как найти в LinkedList i-тый элемент с конца за один проход?»

Уже знаете ответ?

Решение

Можно использовать ту же схему решения. Первый указатель показывает на первый узел в связанном списке, второй на i-тый сначала. Когда второй указатель достигнет конца списка (дойдёт до NULL), первый будет указывать на i-тый элемент с конца.

4.Как определить дублированный элемент в массиве, в котором содержатся элементы типа int от 1 до 100, при условии, что в массиве дублируется только один элемент?

Это вообще задача на логику для средней школы. Многие программисты стремятся её решить длинным перебором/сравнением элементов, но есть куда более рациональный и эстетичный способ.

Догадались, какой?

Решение

  1. Считаем сумму всех чисел от 1 до 100 любым удобным для Вас методом.
  2. Считаем сумму элементов массива.
  3. Вычитаем первое из второго. Получаем… Правильно, получаем значение дублирующегося элемента.
  4. Если надо, находим номера искомых элементов в массиве.

5.Как изменить порядок элементов в строке на обратный без использования вспомогательных классов?

Один из самых популярных экспресс-вопросов. Есть несколько способов выполнения этого задания, но на собеседовании лучше выбрать самый простой. Не забывайте, что Ваш собеседник далеко не всегда может оценить преимущества длинного, но красивого решения.
Неплохо подойдёт что-то типа этого:

Решение

package Javatest.company;
public class Reverse {
    public static String reverseByArray(String s) {
        char[] a = s.toCharArray();
        char[] b = new char[a.length];
        for (int i = 0; i < a.length; i++) {
            b[(a.length - 1) - i] = a[i];
        }
        return new String(b);
    }
    public static void main(String[] args) {
        String string = "Java test";
        System.out.println(reverseByArray(string));
    }
}

6.Напишите программу для сортировки массива, использующую метод пузырька.

Вопросы по сортировке данных присутствуют почти на каждом собеседовании. Они позволяют нанимателю быстро оценить уровень умений кандидата и определить, соответствует ли этот уровень нужному.

Решить это можно так:

Решение

package Javatest.company;
import java.util.Arrays;
public class Bubble {
    public static void main(String args[]) {
        int[] unsorted = {32, 39,21, 45, 23, 3};
        bubbleSort(unsorted);
        int[] test = { 5, 3, 2, 1};
        bubbleSort(test);
    }
    public static void bubbleSort(int[] unsorted){
        System.out.println("unsorted array before sorting : " + Arrays.toString(unsorted));
        for(int i=0; i<unsorted.length -1; i++){
            for(int j= 1; j unsorted[j]){
                    int temp = unsorted[j];
                    unsorted[j] = unsorted[j-1];
                    unsorted[j-1] = temp;
                }
            }
            System.out.printf("unsorted array after %d pass %s: %n", i+1, Arrays.toString(unsorted));
        }
    }
}

7. В чём разница между стеком (Stack) и очередью (Queue)?

Решение

Задавая такие вопросы, ваш собеседник, понятное дело, хочет услышать не заученное определение из учебника или получить ссылку из Википедии, а оценить ваше собственное понимание различия этих двух типов структур данных.
Стек и очередь похожи отсутствием свободного доступа ко всем элементам структуры данных. Главное же отличие заключается в том, что стек – это структура типа LIFO(Last In First Out), где свободный доступ возможен только к последнему добавленному элементу, а при его удалении методом «pop» к элементу, добавленному перед ним. Когда же в стек добавляется новый элемент, доступен становится только он.
Очередь относится к типу FIFO(First In First Out), то есть доступен в ней только первый добавленный элемент. В случае его удаления доступен второй и т.д.

8. Как найти продублированные элементы в массиве, если их больше одного?

Решение

Этот вопрос довольно часто на собеседовании слышат те, кто сумели быстро найти 1 дублирующийся элемент в массиве. Для решения этой задачи можно использовать HashMap. Как Вы, несомненно, знаете, HashMap хранит данные парами – ключ/значение, и создав нужное количество карточек, Вы легко найдёте все повторы и их номера.

9. В чём разница между двусвязным и односвязным списком?

Это один из классических вопросов для телефонного собеседования. Любой программист на него ответит, почти не задумываясь.

Решение

В обоих списках узлы связаны посредством указателей. Только в односвязном списке указатель от каждого узла ведёт исключительно к следующему, и переход возможен только к нему, то есть исключительно в одном направлении. А в двусвязном от каждого узла, кроме первого и последнего, есть возможность перейти как к следующему, так и к предыдущему узлу, то есть двигаться в обоих направлениях.

10. Напишите программу для вывода чисел Фибоначчи

Если вдруг кто-то не знает, числа Фибоначчи – это последовательность, где каждое следующее число после 1 является суммой двух ему предшествующих. То есть ряд чисел Фибоначчи выглядит так: 1,1, 2, 3, 5, 8, 13, 21…

Решить эту задачу можно так:

Решение

package javatest.company;
import java.util.Scanner;
public class Main {
    public static void main(String args[]) {
        System.out.println("Enter number upto which Fibonacci series to print: ");
        int number = new Scanner(System.in).nextInt();
        System.out.println("Fibonacci series upto " + number +" numbers : ");
        for(int i=1; i<=number; i++){
            System.out.print(fibonacci2(i) +" ");
        }
    }
    public static int fibonacci(int number){
        if(number == 1 || number == 2){
            return 1;
        }
        return fibonacci(number-1) + fibonacci(number -2); 
    }
    public static int fibonacci2(int number){
        if(number == 1 || number == 2){
            return 1;
        }
        int fibo1=1, fibo2=1, fibonacci=1;
        for(int i= 3; i<= number; i++){
            fibonacci = fibo1 + fibo2; 
            fibo1 = fibo2;
            fibo2 = fibonacci;
        }
        return fibonacci;
    }
}

11. Напишите программу, которая определит, является ли заданное число палиндромом, не используя сторонние библиотеки

Палиндром – это набор знаков (слово, число, фраза), в котором все знаки при прямом прочтении полностью совпадают со знаками при обратном прочтении.
То есть палиндромами являются числа 66, 13431, 789987 и т.д.

Решение

  1. Для определения значения каждого символа в числе можно использовать оператор /. Например: 66/10 вернёт 6.
  2. А для нахождения последнего символа в числе оператор %.
    66%10=6
    123%10=3
  3. Сравниваем полученные значения и делаем выводы.

Можно пойти другим путём и развернуть число, используя рекурсию.

Например, так:

package com.Javatest;
public class Palindrome {
    public static int recursion(int n) {
        if (n < 10) {
            return n;
        }
        else {
            System.out.print(n % 10 + " ");
            return recursion(n / 10);
        }
    }
    public static void main(String[] args) {
        System.out.println(recursion(123)); 
    }
}

А после этого дописать этот код так, чтобы он сравнивал полученные цифры.

12. Напишите программу, которая проверит, является ли заданное слово палиндромом

Задача, в принципе, аналогичная предыдущей, но с существенным отличием — использовать операторы / и % не получится.
Используем рекурсию и получим простое и красивое решение:

Решение

package Javatest.com;
public class Palword {
    public static String recursion(String s) {
        if (s.length() == 1) {
            return "YES";
        } else {
            if (s.substring(0, 1).equals(s.substring(s.length() - 1, s.length()))) {
                if (s.length() == 2) {
                    return "YES";
                }
                return recursion(s.substring(1, s.length() - 1));
            } else {
                return "NO";
            }
        }
    }
    public static void main(String[] args) {
        System.out.println(recursion("ABBA")); 
    }
}

13. Что такое бинарное дерево поиска?

Решение

Бинарное, или двоичное дерево поиска – это структура данных, каждый узел в которой может иметь от 1 до 2 подузлов (детей) или не иметь их вовсе.

Расположение данных в бинарном дереве имеет ряд ограничений:

  1. Как и во всех деревьях, любой узел бинарного дерева не может иметь более одного родителя.
  2. Данные в дереве распределяются в зависимости от их значений. Если значение подузла (ребёнка) меньше, чем значение узла (родителя), этот подузел становиться левым или ребёнком левого подузла, если левый подузел уже существует. Соответственно, если значение подузла больше значения узла, то он становится правым или ребёнком правого.

Применяются бинарные деревья в реализации ассоциативных массивов и множеств, например TreeMap или TreeSet, в некоторых алгоритмах вычислительной геометрии.

14. Напишите программу для реализации структуры данных Stack.

Этот вопрос позволяет Вам продемонстрировать свои навыки владения стандартными методами (push и pop) для работы с этой структурой данных. При выполнении этой задачи Вам нужно будет использовать массив или связный список для хранения элементов.
Написать можно, например, программу стандартного калькулятора.

15. Как развернуть LinkedList, используя рекурсию и итерацию?

Ещё один пример очень популярного вопроса. Есть много способов изменения порядка элементов в связанном списке. В следующей статье я рассчитываю подробно осветить их все.
Ждите! Или пишите свои варианты этой программы, не заглядывая в «авторскую версию»!
for java interview

В заключение

Не забывайте, что решая ту или иную задачу на собеседовании, желательно разъяснять каждый логический шаг интервьюеру. На стартовом собеседовании оценивают не только скорость и правильность решения поставленных задач, но и логику мышления в целом.
Именно поэтому иногда даже неполное решение сложной задачи позволит интервьюеру оценить ваши знания как достаточные для вакантной должности.
Даже если Вы опытный программист с десятками реализованных проектов портфолио, не поленитесь перед собеседованием повторить теорию. Ведь ответ «ну это работает где-то так… и вообще, за последние 3 года я ни разу не пользовался этой структурой данных» вряд ли устроит интервьюера.
Часть материалов переведена из этого источника.

Креатива Вам и удачи на собеседовании!

Другие статьи по теме

Подборка материалов и видеокурсов по Java

6 книг по Java для программистов любого уровня

Перед устройством на постоянную работу или перед получением какого-либо крупного проекта потенциального разработчика обязательно попросят выполнить тестовое задания. В зависимости от компании и проекта оно может быть как непосредственно связано с будущими задачами задачами разработчика, так и носить общий характер. В случае успешного прохождения тестового задания потенциальный соискатель нанимается на проект. Соответственно, в интересах разработчика выполнить тестовое задание заинтересовавшего нанимателя.

От выполнения каких тестовых лучше отказаться

Не все тестовые задания нужно выполнять, да и не во всех случаях это требуется делать. Рекомендуется проявлять осторожность в следующих ситуациях:

  1. Тестовое задание и является проектом. Причем за его выполнение вам ничего не выплатят. Это говорит о том, что, скорее всего, потенциальный заказчик хочет, чтобы кто-то выполнил бесплатно его проект. Вам могут обещать сотрудничество в дальнейшем, но, вероятно, что на бесплатном выполнении проекта все и закончится. Исключение можно сделать в том случае, если проект действительно очень легкий для вас, а потенциальный заказчик показал задания для будущих проектов.
  2. Тестовое задание является частью проекта. Ситуация очень похожа на предыдущую, но только в этот раз вам предлагается выполнить часть проекта в качестве теста. Задание должно быть оплачиваемым в случае успешного выполнения: отдельно или в рамках всего проекта. Также оно не должно составлять более ⅓ от объема основной задачи. Если эти условия нарушаются, то лучше отказаться от выполнения подобного тестового.
  3. Тестовое задание слишком объемное. Оно не должно занимать у потенциального разработчика больше одного рабочего дня. Если оно более объемное, то приступать к его выполнению нецелесообразно, даже если оно оплачивается. Дело в том, что вы потратите то время, которое могли бы потратить на поиск более подходящей позиции, без гарантий устройства или получения интересующих заданий.
  4. Тестовое задание совершенно не соответствует проекту, над которым вы должны работать. Разработчик с помощью тестового должен понять, над чем будет работать в случае успешного выполнения. К заданиям, не соответствующим проекту лучше относится с осторожностью, так как по итогу вы можете столкнуться с тем, к чему не готовы и испортить свою репутацию.

Если тестовое соответствует одному или нескольким из описанных пунктов, то от них рекомендуется отказаться. Однако всегда смотрите на ситуацию и собственное желание. Возможно, что вы готовы рискнуть и потратить время на его выполнение и при этом уверены в порядочности потенциального заказчика. Тогда тестовое целесообразнее выполнить.

Признаки хорошего тестового

Тестовое задание — это универсальная проверка кандидата на пригодность к работе над тем или иным проектом. Собеседование не всегда способно корректно определить навыки, а в портфолио могут оказаться проекты, над которыми кандидат на самом деле не работал.

В первую очередь нужно обратить на приблизительное время, которое вам потребуется для выполнения тестового. Если оно не оплачивается вообще, то его выполнение должно занять максимум 3 часа. В противном случае приступать к выполнению нецелесообразно, так как лучше потратить это время на поиск других вакансий. Если же оно оплачивается, то на выполнение вполне можно выделить рабочий день.

Обращайте внимание на то, стоит ли развертывать какую-то дополнительную среду разработки или другую инфраструктуру для выполнения проекта. В идеале она должна быть минимальной, например, только установка одной-двух программ и скачивание исходных файлов. Исключение можно сделать, опять же, только в том случае, когда тестовое задание оплачивается.

Зачем нужны тестовые задания

Тестовое задание нужно для определения навыков кандидата на примере конкретной задачи. Оно способно дать более объективную оценку способностей и опыта, чем заявления в резюме, формальное образование и даже примеры работ из портфолио. Помимо оценки выполнения самого задания, потенциальный заказчик оценивает и другие профессиональные качества: умение кандидата рассчитывать время выполнения задач, оперативность принятия решений, нестандартное мышление, пунктуальность.

Пример тестового задания. Здесь кандидату, скорее всего, потребуется задавать уточняющие вопросы и получать дополнительные исходные файлы

В идеале, кандидат должен не просто справится с тестовым, но и зарекомендовать себя как ответственного сотрудника. Рассмотрим основные советы выполнения тестового задания.

Совет 1: Не соглашайтесь сразу

Не нужно сразу на предложение тестового задания со стороны потенциального заказчика говорить “Да”. Внимательно изучите условия, а также поищите информацию о работодателе, если не сделали этого ранее. Адекватный заказчик должен понимать, почему вы не беретесь сразу за тестовое. Если вас торопят с решением, то это может говорить о проблемах в работе с этим человеком в будущем. Помните, что не только заказчик вас выбирает, но и вы тоже выбираете заказчика.

Естественно, не нужно брать слишком много времени “на подумать”. В большинстве случаев задание не требует долгого выполнения, поэтому анализировать там тоже особо нечего. На детальный анализ такого тестового должно уйти не более 15 минут. Однако, пока не выясните все детали, которые считаете важными, не соглашайтесь на выполнение. Давать согласие можно только в том случае, когда вы точно знаете, что от вас хотят и что будет в случае успешного выполнения.

Совет 2: Задавайте вопросы

Правда, делайте это сугубо по делу. Так вы покажете свою заинтересованность и, возможно, экспертность. Также они полезны и для лучшего понимания задачи. Если что-то непонятно в условиях задачи или даже в процессе выполнения, то не стесняйтесь задавать вопросы. Никто за них ругать не будет, но, правда, могут решить, что у вас недостаточно профессиональных навыков. Хотя, если вопросы по-делу и не являются какими-то элементарными, то такой исход событий маловероятен.

Если вам не понятно что-то в формулировках к заданию, вы встретили в них противоречащие друг другу пункты, то обязательно скажите об этом HR`у или тому, кто вас собеседует. Обычно внимательность к таким деталям со стороны кандидата воспринимают положительно, поэтому это может хорошо повлиять на перспективы получения реальных проектов.

Совет 3: Не воруйте тестовые задания

Сделать это достаточно сложно, особенно, если вы пытаетесь получить какой-то проект на фрилансе, но вполне реально. Иногда заказчик решает не самостоятельно составлять техническое задание для разработчика, а искать готовые варианты в интернете. Для некоторых задач такие действительно есть и их много. На такие шаблонные задания легко найти варианты решения в свободном доступен. Однако делать это категорически не рекомендуется.

Кража тестового легко вскрывается, в первую очередь по устаревшему синтаксису, чужим комментариям и даже разному стилю написания кода. Для того, кто проверил немало в своей жизни тестовых заданий, выявить, что его сделали не вы, будет достаточно просто.

Однако, если вы нашли решения на какое-то тестовое задание, то можете изучить его и сравнить с собственным. Но у вас должно быть уже всего завершено, чтобы было с чем сравнивать. Не нужно пытаться заполнить пробелы в знаниях с помощью скачанного где-то решения. Если даже вам доверят в итоге работу, то обман все равно вскроется, так как вы вряд ли сможете работать с реальным проектом, если не смогли выполнить самостоятельно тестовое.

Совет 4: Обращайте внимание на детали

К выполнению тестового задания требуется подойти со всей ответственностью, особенно, если на потенциальный проект претендует несколько кандидатов. В таком случае, разумно будет подумать не только о том, чтобы это просто работало с технической точки зрения, но и о качестве написанного кода. В первую очередь избегайте всевозможных костылей, если задание возможно корректно реализовать без них. Использование костылей в коде, когда есть возможность сделать все в соответствии с ТЗ без их использования, покажет ваш непрофессионализм. Лучше потратить больше времени на поиск более элегантного решения, чем отдавать “кривой” код.

Важно задуматься над оформлением кода:

  • Делите его на смысловые блоки и старайтесь не перемешивать все в кучу. Выполненное задание, которое удобно читать, проверяется быстрее и при этом дает конкурентное преимущество перед другими соискателями.
  • Не используйте слишком много сокращений. Да, это возможность показать свой профессионализм, но лучше соблюдать баланс, так как проверяющий может не понять их.
  • Не делайте слишком большой и примитивный код. Это уже другая крайность. Некоторые конструкции, если это возможно, лучше сократить или использовать более изящный вариант решения задачи. Слишком громоздкий код хуже, чем использование большого количества сокращений, так как он утяжеляет проект и делает сложной его дальнейшую оптимизацию.
  • Комментируйте код. Опять же, это нужно для читаемости и лучшего понимания, за что отвечает тот или иной его кусок. Часто сначала проверять тестовое может человек, далекий от программирования, поэтому комментирование поможет ему быстрее справится с работой и передать на проверку уже более профессиональным коллегам.

Пример читаемого кода стилей

Совет 5: Проверяйте работоспособность кода перед отправкой

Это очень важно и очевидно, но иногда начинающие разработчики забывают про этот момент. Перед отправкой обязательно нужно проверить на работоспособность все элементы, а не только чтобы все в общем работало. Также важно, чтобы задание, которое вы выполнили, открывалось на всех основных устройствах, форматах экрана, разрешениях, популярных браузерах. Если вдруг у проверяющего разъедется верстка или что-то не сработает просто потому, что он открыл ваше задание на проверку в другом браузере, то есть риск, что вашу кандидатуру отвергнут. Перед отправкой тестового тщательно проверьте, чтобы все работало.

Что нужно учитывать кроме тестового

Корректное выполнение тестового задания очень важно для получения проекта или устройства в штат, но обращать внимание нужно не только на него. Вот, что еще поможет получить проект или интересующую вакансию:

  1. Ваше резюме. Первое, на что смотрит потенциальный клиент или работодатель. Грамотно составленное резюме поможет получить тестовое задание, если такое предусмотрено. Дело в том, что и тестовое выдают не всем, а только тем, кто заинтересовал заказчика своим резюме, портфолио. У нас в блоге уже есть подробная статья про составление резюме для веб-разработчика и программиста.
  2. Портфолио. Чем оно более релевантно проекту, на который вы претендуете, тем выше шанс того, что вашу кандидатуру одобрят. Возможно, даже сделают это без тестового задания. Однако портфолио тоже нужно грамотно оформить и презентовать. Подробно про это читайте в нашей отдельной статье.
  3. Профиль на фриланс-биржах и в социальных сетях. Больше актуально для тех, кто ищет проекты на фрилансе, особенно, если поиск идет через биржи или социальные сети. Напишите информацию о себе, покажите в профиле примеры работ, отзывы клиентов. Правильно оформленный профиль на тематических ресурсах можно одновременно использовать и как резюме, и как портфолио.
  4. Умение вести переговоры. Пригодится на всех этапах найма и, тем более, уже во время работы. Вы должны уметь задавать вопросы по делу, договариваться об оплате, корректно оценивать сроки, презентовать себя как адекватного человека.

Заключение

Тестовое задание — это одна из обязательных процедур для устройства на позицию разработчика или получения крупного проекта. Однако, перед тем, как выполнять его, нужно убедиться в порядочности заказчика, собственных силах и соответствию ТЗ проекту. Если у вас действительно есть необходимые компетенции для интересующего проекта, то сложностей с тестовым возникнуть не должно. Но даже если они возникли, то не стоит стесняться обратиться за разъяснениями к потенциальному заказчику или работодателю. Тестовое не всегда может составлено корректно, а иногда это и вовсе может быть элементом проверки на внимательность к деталям.

Понравилась статья? Поделить с друзьями:
  • Как исправить неровный паркет
  • Как найти настройки звука на телефоне
  • Как найти вес на подвесе
  • Как найти замены аккумулятору
  • Application load error 5 0000065434 metro 2033 как исправить ошибку