← Назад к вопросам

FizzBuzz

2.2 Middle🔥 191 комментариев
#JavaScript Core

Условие

Напишите функцию fizzBuzz(n), которая выводит числа от 1 до n с заменами.

Требования

  1. Для чисел, кратных 3, выводить "Fizz"
  2. Для чисел, кратных 5, выводить "Buzz"
  3. Для чисел, кратных и 3, и 5, выводить "FizzBuzz"
  4. Для остальных чисел выводить само число

Примеры

fizzBuzz(15);
// 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz

fizzBuzz(5);
// 1, 2, Fizz, 4, Buzz

Бонус

Сделайте функцию настраиваемой - чтобы можно было передать правила замены: fizzBuzz(n, { 3: "Fizz", 5: "Buzz", 7: "Bazz" })

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

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

Базовое решение

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

function fizzBuzz(n: number): string[] {
  const result: string[] = [];
  
  for (let i = 1; i <= n; i++) {
    // Проверяем делимость на 15 первой (это и 3, и 5)
    if (i % 15 === 0) {
      result.push("FizzBuzz");
    } else if (i % 3 === 0) {
      result.push("Fizz");
    } else if (i % 5 === 0) {
      result.push("Buzz");
    } else {
      result.push(i.toString());
    }
  }
  
  return result;
}

console.log(fizzBuzz(15).join(", "));
// 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz

Анализ:

  • Временная сложность: O(n)
  • Пространственная сложность: O(n)
  • Главное: проверить 15 перед 3 и 5, иначе будет неправильно

Улучшенное решение: Конкатенация

Более элегантный способ без многоуровневых условий:

function fizzBuzzConcat(n: number): string[] {
  const result: string[] = [];
  
  for (let i = 1; i <= n; i++) {
    let output = "";
    
    // Собираем строку из частей
    if (i % 3 === 0) output += "Fizz";
    if (i % 5 === 0) output += "Buzz";
    
    // Если ничего не добавили, используем число
    result.push(output || i.toString());
  }
  
  return result;
}

Преимущества:

  • Легче добавлять новые правила
  • Меньше вложенности if-else
  • Более читаемый код

Бонус: Настраиваемая версия

Передаём правила в виде объекта:

interface FizzBuzzRules {
  [key: number]: string;
}

function fizzBuzzCustom(
  n: number,
  rules: FizzBuzzRules = { 3: "Fizz", 5: "Buzz" }
): string[] {
  const result: string[] = [];
  const sortedDivisors = Object.keys(rules)
    .map(Number)
    .sort((a, b) => a - b); // Сортируем делители
  
  for (let i = 1; i <= n; i++) {
    let output = "";
    
    // Проходим по всем делителям в порядке возрастания
    for (const divisor of sortedDivisors) {
      if (i % divisor === 0) {
        output += rules[divisor];
      }
    }
    
    result.push(output || i.toString());
  }
  
  return result;
}

// Использование
console.log(fizzBuzzCustom(15).join(", "));
// 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz

console.log(fizzBuzzCustom(21, { 3: "Fizz", 5: "Buzz", 7: "Bazz" }).join(", "));
// 1, 2, Fizz, 4, Buzz, Fizz, Bazz, 8, Fizz, Buzz, 11, Fizz, 13, Bazz, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz

Продвинутое решение: Функциональный стиль

Используем map и функции высшего порядка:

function fizzBuzzFunctional(
  n: number,
  rules: FizzBuzzRules = { 3: "Fizz", 5: "Buzz" }
): string[] {
  const divisors = Object.keys(rules).map(Number);
  const lcm = divisors.reduce((a, b) => 
    (a * b) / gcd(a, b), 1
  );
  
  return Array.from({ length: n }, (_, i) => {
    const num = i + 1;
    const output = divisors
      .filter(d => num % d === 0)
      .map(d => rules[d])
      .join("");
    
    return output || num.toString();
  });
}

function gcd(a: number, b: number): number {
  return b === 0 ? a : gcd(b, a % b);
}

Тестирование

// Базовые случаи
console.log(fizzBuzz(5).join(", "));
// 1, 2, Fizz, 4, Buzz

console.log(fizzBuzz(15).join(", "));
// 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz

// Граничные случаи
console.log(fizzBuzz(1));
// ["1"]

console.log(fizzBuzz(0));
// []

Сравнение подходов

ПодходГибкостьЧитаемостьСложностьМасштабируемость
БазовоеНизкаяСредняяO(n)Плохая
КонкатенацияСредняяВысокаяO(n)Хорошая
НастраиваемоеВысокаяХорошаяO(n*m)Отличная
ФункциональноеВысокаяСредняяO(n*m)Отличная

Рекомендации для собеседования

  1. Начните с базового решения — покажите понимание задачи
  2. Подумайте о порядке проверок — 15 перед 3 и 5 важен
  3. Предложите улучшение — конкатенация более элегантна
  4. Обсудите бонус — настраиваемость показывает опыт
  5. Объясните трейд-офф — гибкость vs простота

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

FizzBuzz | PrepBro