javascript

JavaScript. Готовимся к live-coding

  • воскресенье, 2 февраля 2025 г. в 00:00:05
https://habr.com/ru/articles/878594/

Всем привет! Сейчас без live-coding'a никуда: на собеседованиях часто дают одну-две задачки, которые нужно решить за определённое время. Сами задачи могут быть несложными (не супер-пупер алгоритмическими), но новички могут переволноваться и не справиться с ними.

Поэтому в этой статье я хотел бы описать типовые задачи, которые встречаются в этой секции на позицию frontend или backend разработчика (если бэк на JS). Это поможет вам получить общее представление о том, что может ждать вас. Не забываем подписываться на мой канал в Telegram, там тоже есть, что почитать.

Поеееехалииии 🏎️💨

Понимание JavaScript

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

  • Переменные, типы данных (особенно строки).

  • Простые операторы (+, -, *, /, %, >, < и тд) и побитовые (&, |, ~, <<, >>, >>>).

  • Условный оператор, циклы (особенно уметь использовать while и for.

  • Функции. Рекурсия - очень важная концепция. Иногда встречаются задачи, которые можно решить только с её помощью. Также не менее важно понимать замыкания, контекст выполнения и области видимости.

  • Структуры данных - массивы (80% задач), объекты/мапы/хэш-таблицы.

  • Регулярные выражения.

Как говорится это база. Идем дальше 🚀

Подходы к решению задач в секции live-coding

Рассмотри основной алгоритм решения задач:

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

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

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

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

  5. Опять тестируем - используйте предоставленные примеры, а также создавайте свои тестовые случаи.

  6. Исправляем, рефакторим, тестируем.

  7. Говорим, что готово.

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

В бой

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

Простые задачи

Функция sumRange принимает два числа start и end. Необходимо найти сумму всех чисел в заданном диапазоне.

// Тестовые данные
console.log(sumRange(1, 5)); // 15
console.log(sumRange(0, 10)); // 55
console.log(sumRange(-3, 3)); // 0
Ответ

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

// Тестовые данные
console.log(reverseNumber(123)); // 321
console.log(reverseNumber(-456)); // -654
console.log(reverseNumber(1000)); // 1
console.log(reverseNumber(0)); // 0
Ответ

https://github.com/atrapeznikov/live-coding/blob/main/reverseNumber.js

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

// Тестовые данные
console.log(isPerfectSquare(16)); // true
console.log(isPerfectSquare(14)); // false
console.log(isPerfectSquare(0)); // true
console.log(isPerfectSquare(25)); // true
Ответ

Массивы

Реализовать функцию minMax(), которая принимает массив и возвращает максимальное и минимальное значение. Решить нужно не использую Math.min() и Math.max().

// Тестовые данные
console.log(findMinMax([4, 3, 5, 3, 2])); // {min: 2, max: 5}
console.log(findMinMax([4, 4, 7, 2, 1, 10])); // {min: 1, max: 10}
console.log(findMinMax([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); // {min: 1, max: 10}
Ответ

Необходимо в массиве найти второе наибольшее число.

// Тестовые данные
console.log(secondLargest([10, 20, 4, 45, 99])); // 45
console.log(secondLargest([5, 5, 5])); // null
console.log(secondLargest([1])); // null
Ответ

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

// Тестовые данные
console.log(findPairs([2, 4, 3, 7, 8, 1], 9)); // [[7, 2], [8, 1]]
console.log(findPairs([1, 2, 3, 4, 5], 10)); // []
console.log(findPairs([0, -1, -2, 2, 1], 0)); // [[-1, 1], [-2, 2]]
Ответ

Строки

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

// Тестовые данные
console.log(isPalindrome("A man, a plan, a canal, Panama!")); // true
console.log(isPalindrome("No 'x' in Nixon")); // true
console.log(isPalindrome("Was it a car or a cat I saw?")); // true
console.log(isPalindrome("Eva, I see bees in a cave")); // false
Ответ

Напишите функцию, проверяющую, являются ли две строки анаграммами друг друга (регистр букв не имеет значения)

// Тестовые данные
console.log(isAnagram("finder", "Friend")); // true
console.log(isAnagram("hello", "bye")); // false
console.log(isAnagram("listen", "silent")); // true
console.log(isAnagram("rail safety", "fairy tales"));
Ответ

Напишите функцию для поиска первого неповторяющегося символа в строке. Возвращайте ноль (null), если все символы повторяются.

// Тестовые данные
console.log(firstNonRepeatingChar("swiss")); // "w"
console.log(firstNonRepeatingChar("aabbcc")); // null
console.log(firstNonRepeatingChar("javascript")); // "j"
Ответ

Напишите функцию для подсчета количества гласных и согласных в строке.

// Тестовые данные
console.log(countVowelsAndConsonants("hello")); // { vowels: 2, consonants: 3 }
console.log(countVowelsAndConsonants("JavaScript")); // { vowels: 3, consonants: 7 }
console.log(countVowelsAndConsonants("12345")); // { vowels: 0, consonants: 0 }
Ответ

Рекурсия

Напишите функцию, которая вычисляет факториал числа.

// Тестовые данные
console.log(factorial(0)); // 1
console.log(factorial(1)); // 1
console.log(factorial(2)); // 2
console.log(factorial(3)); // 6
Ответ

Необходимо написать функцию которая превращает многомерный массив в одномерный.

// Тестовые данные
console.log(_flatten([1, 2, 3]));               // [1, 2, 3]
console.log(_flatten([1, [2, 3], 4]));          // [1, 2, 3, 4]
console.log(_flatten([[1, 2], [3, 4]]));        // [1, 2, 3, 4]
console.log(_flatten([1, [2, [3, [4, 5]]]]));   // [1, 2, 3, 4, 5]
console.log(_flatten([]));                      // []
Ответ

Написать функцию которая возвращает последовательность фибоначи.

// Тестовые данные
console.log(fibonacci(0)); // 0
console.log(fibonacci(1)); // 1
console.log(fibonacci(2)); // 1
Ответ

Напишите рекурсивную функцию для определения длины строки.

// Тестовые данные
console.log(stringLength("hello")); // 5
console.log(stringLength("JavaScript")); // 10
console.log(stringLength("")); // 0
Ответ

Напишите рекурсивную функцию для поиска максимального элемента в массиве.

// Тестовые данные
console.log(findMax([1, 5, 3, 9, 2])); // 9
console.log(findMax([-1, -5, -3])); // -1
console.log(findMax([10])); // 10
Ответ

Асинхронные операции

Необходимо создать функцию fetchRetryer(), которая будет выполнять запрос на определенный API и повторять его до 5 раз, пока не получит ответ (статус 200). Если после 5 повторов сервер не отвечает - возвращаем ошибку.

// Пример использования
fetchRetryer("https://jsonplaceholder.typicode.com/posts/1")
    .then((res) => res.json())
    .then((data) => console.log("Success:", data))
    .catch((err) => console.error("Failed:", err.message));

fetchRetryer("https://invalid-url.example")
    .then((res) => res.json())
    .catch((err) => console.error("Failed after retries:", err.message));
Ответ

Реализуйте функцию _promiseAll.

// Тестовые данные
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
const promise4 = new Promise((resolve) => setTimeout(resolve, 100, 4));

_promiseAll([promise1, promise2, promise3, promise4])
    .then((results) => {
        console.log(results); // Output: [1, 2, 3, 4]
    })
    .catch((error) => {
        console.error(error);
    });

const promise5 = Promise.reject("Error occurred");

customPromiseAll([promise1, promise2, promise5])
    .then((results) => {
        console.log(results);
    })
    .catch((error) => {
        console.error(error); // Output: Error occurred
    });
Ответ

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

Должны выполняться следующие условия:

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

  • Если время выполнения исходной функции превышает временной лимит, новая функция должна вернуть сообщение: "Превышен лимит исполнения".

// Тестовые данные
const fn = async (n) => {
    await new Promise((res) => setTimeout(res, 100));

    return n * n;
};

console.log(asyncLimit(fn, 50)(5)); // rejected превышен лимит
console.log(asyncLimit(fn, 150)(5)); // resolve 25

const fn2 = async (a, b) => {
    await new Promise((res) => setTimeout(res, 120));

    return a + b;
};

console.log(asyncLimit(fn2, 100)(1, 2));
console.log(asyncLimit(fn2, 150)(1, 2));
Ответ

Реализация встроенных функций (полифилы)

Реализуйте метод _filter для массивов.

// Тестовые данные
console.log([1, 2, 3, 4, 5]._filter(n => n % 2 === 0)); // [2, 4]
console.log(["apple", "banana", "cherry"]._filter(fruit => fruit.includes("a"))); // ["apple", "banana"]
console.log([10, 20, 30]._filter((num, index) => index % 2 === 0)); // [10, 30] 
Ответ

Реализуйте метод _map для массивов.

// Тестовые данные
console.log([1, 2, 3]._map(n => n * 2)); // [2, 4, 6]
console.log(["a", "b", "c"]._map(letter => letter.toUpperCase())); // ["A", "B", "C"]
console.log([10, 20, 30]._map((num, index) => num + index)); // [10, 21, 32]
Ответ

Реализуйте метод _reduce для массивов.

// Тестовые данные
console.log([1, 2, 3, 4]._reduce((acc, num) => acc + num)); // 10
console.log([1, 2, 3, 4]._reduce((acc, num) => acc + num, 10)); // 20 
console.log(["a", "b", "c"]._reduce((acc, char) => acc + char)); // "abc"
console.log([2, 3, 4]._reduce((acc, num) => acc * num, 1)); // 24
Ответ

Реализуйте класс EventEmitter.

// Пример использования
const emitter = new EventEmitter();

function responseToEvent(data) {
    console.log(`Event received with data: ${data}`);
}

emitter.on('dataReceived', responseToEvent);
emitter.emit('dataReceived', { id: 1, message: 'Hello, World!' });
emitter.off('dataReceived', responseToEvent);
emitter.emit('dataReceived', { id: 2, message: 'This will not be logged.' });

// Register a one-time event listener
emitter.once('dataReceivedOnce', (data) => {
    console.log(`One-time event received: ${data}`);
});
emitter.emit('dataReceivedOnce', 'This will be logged once.');
emitter.emit('dataReceivedOnce', 'This will not be logged.');
Ответ

Регулярные выражения

Напишите функцию, которая принимает строку в качестве аргумента и возвращает количество гласных, содержащихся в этой строке. Гласными являются «a», «e», «i», «o», «u».

// Тестовые данные
console.log(countVowels("hello")); // 2
console.log(countVowels("JavaScript")); // 3
console.log(countVowels("xyz")); // 0
Ответ

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

// Тестовые данные
console.log(extractDomain("https://www.google.com")); // "google.com"
console.log(extractDomain("http://example.org")); // "example.org"
console.log(extractDomain("https://sub.domain.com/path")); // "sub.domain.com"
console.log(extractDomain("invalid-url")); // null
Ответ

Дополнительные задачи

Написать функцию, которая проверит строку и вернёт в результате true или false в зависимости от того, является ли данная последовательность скобок валидной.

// Тестовые данные
console.log(isValidParentheses("()[]{}")); // true
console.log(isValidParentheses("([{}])")); // true
console.log(isValidParentheses("(]")); // false
console.log(isValidParentheses("([)]")); // false
console.log(isValidParentheses("{[]}")); // true
Ответ

Разработайте стек, который поддерживает операции push, pop, top и извлечение минимального элемента за постоянное время O(1).

// Пример использования
const minStack = new MinStack();
minStack.push(5);
minStack.push(3);
minStack.push(7);
console.log(minStack.getMin());
minStack.pop();
console.log(minStack.getMin());
minStack.pop();
console.log(minStack.getMin());
Ответ

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

// Пример использования:
const logs = [
  "user1 login",
  "user2 login",
  "user1 click",
  "user3 login",
  "user1 logout",
  "user2 click",
  "user2 logout",
  "user3 click",
  "user3 logout",
];

console.log(analyzeLogs(logs));
// { user1: 3, user2: 3, user3: 3 }
Ответ

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

// Пример использования:
const tasks = [
  () => new Promise((res) => setTimeout(() => res("Task 1"), 1000)),
  () => new Promise((res) => setTimeout(() => res("Task 2"), 500)),
  () => new Promise((res) => setTimeout(() => res("Task 3"), 1200)),
  () => new Promise((res) => setTimeout(() => res("Task 4"), 300)),
];

parallelTaskRunner(tasks, 2).then(console.log);
// ["Task 1", "Task 2", "Task 3", "Task 4"]
Ответ

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

Не забывайте, что успешное выполнение задач в секции live-coding требует постоянной практики и упорства. Формула проста: чем больше вы практикуетесь, тем увереннее будете себя чувствовать на собеседованиях. Всё просто!

Желаю вам удачи!

📢 Подписывайтесь на мой канал в Telegram, где я делюсь интересной и полезной информацией.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Твой уровень
0% Стажер0
33.33% Middle2
16.67% Senior1
0% Team Lead0
0% Tech Lead0
50% Meme Lead3
Проголосовали 6 пользователей. Воздержавшихся нет.