Что такое bruteforce

В этом уроке ты
  • Узнаешь, что такое метод полного перебора (bruteforce) и где он применяется.
  • Научишься использовать bruteforce для поиска всех возможных решений задачи.
  • Разберёшься, как оценивать время и память, затрачиваемые на полный перебор.
Полный перебор (Bruteforce)

Полный перебор (bruteforce) — это метод решения задачи, при котором последовательно перебираются все возможные комбинации без какой-либо оптимизации.

Пример из жизни

Представь, что ты забыл пароль от телефона, но знаешь, что он состоит из трёх цифр. Единственный способ узнать пароль — проверить все возможные варианты: 000, 001, 002, …, 999

Этот метод гарантированно найдёт верное решение, но он может занимать очень много времени, когда количество комбинаций слишком велико.

Bruteforce на собеседованиях

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

Перебор всех n-значных паролей

Ниже приведён пример кода, который перебирает все возможные n-значные комбинации, если пароль может содержать только цифры 0, 1 и 2:

class Solution
{
    static void BruteForceHelper(List<int> curr, int n, List<List<int>> result)
    {
        if (curr.Count == n)
        {
// Нашли полную комбинацию, добавляем в результат
            result.Add(new List<int>(curr)); // Копируем список, чтобы избежать изменений
            return;
        }

// Перебираем возможные цифры: 0, 1, 2
        for (int i = 0; i < 3; i++)
        {
// Добавляем число в текущую последовательность
            curr.Add(i);
// Рекурсивный вызов для следующего шага
            BruteForceHelper(curr, n, result);
// Убираем последнее число (откат назад)
            curr.RemoveAt(curr.Count - 1);
        }
    }

// Время: O(3^n)
// Память: O(3^n)
    public static void BruteForce(int n)
    {
        List<List<int>> result = new List<List<int>>();
        BruteForceHelper(new List<int>(), n, result);

// Выводим все возможные комбинации
        foreach (var combo in result)
        {
            foreach (var num in combo)
            {
                Console.Write(num);
            }
            Console.WriteLine();
        }
    }

// Запуск перебора для 3-значного кода (000 - 222)
    static void Main()
    {
        BruteForce(3);
    }
}
Визуализация полного перебора

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

Оценка времени и памяти полного перебора

Рассмотрим пример с 4-значным кодом, где каждая цифра может принимать значения от 0 до 9: Количество возможных комбинаций: 10 * 10 * 10 * 10 = 10^4 = 10 000.

Если же мы возьмём 100-значный код, в котором каждая цифра может быть только 0 или 1, количество вариантов равно 2^100 = 1,26 * 10^30 . Перебрать все эти комбинации за разумное время невозможно на обычном компьютере. Если взять средний компьютер, то перебор 1,26 * 10^30 вариантов займет десятки тысяч лет!

Обобщённая оценка сложности:

  • Время:  O(n^m) , где  n  — количество возможных значений для каждого символа, а  m  — длина комбинации.
  • Память:  O(n^m) , если мы хотим хранить все варианты сразу.

Такая зависимость от  n^m  называется экспоненциальной, что делает bruteforce неэффективным для большого объема входных данных.

Когда использовать bruteforce?

Bruteforce может подойти, если:

  1. Количество вариантов не слишком велико. Тогда перебор всех решений занимает разумное время.
  2. Задачу нельзя решить быстрее никакими другими методами (или оптимизация не оправдана для конкретной ситуации).
Что дальше

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