Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. BFS: Кратчайший путь
bfs_shortest_path

BFS: Кратчайший путь

Word Ladder, Open the Lock, Course Schedule II.

BFS: Кратчайший путь

Поиск кратчайшего пути в невзвешенном графе. Word Ladder, Open the Lock, Perfect Squares.

#1. Word Ladder (LeetCode 127) 🔴 Hard

Ссылка: https://leetcode.com/problems/word-ladder/

Условие: Даны два слова beginWord и endWord, а также словарь wordList. Найдите длину кратчайшей последовательности преобразования от beginWord к endWord, где:

  • Каждое преобразование меняет ровно одну букву
  • Каждое промежуточное слово должно быть в wordList

Верните количество слов в кратчайшей последовательности или 0, если пути не существует.

Примеры:

Ввод: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Вывод: 5
Объяснение: "hit" -> "hot" -> "dot" -> "dog" -> "cog"

Ввод: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Вывод: 0

Ограничения:

  • 1 <= beginWord.length <= 10
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • Все слова состоят из строчных английских букв

💡 Подсказка: Используйте BFS. Для каждого слова генерируйте все возможные варианты с заменой одной буквы (26 × длина слова).

Решение:

from collections import deque def ladderLength(beginWord, endWord, wordList): if endWord not in wordList: return 0 wordList = set(wordList) queue = deque([(beginWord, 1)]) while queue: word, steps = queue.popleft() if word == endWord: return steps # Генерируем все варианты с одной изменённой буквой for i in range(len(word)): for c in 'abcdefghijklmnopqrstuvwxyz': next_word = word[:i] + c + word[i+1:] if next_word in wordList: wordList.remove(next_word) # Помечаем как посещённое queue.append((next_word, steps + 1)) return 0

Объяснение:

  • BFS находит кратчайший путь
  • Для каждого слова пробуем все 26 букв на каждой позиции
  • Удаление из wordList заменяет отдельный set visited

Сложность:

  • Время: O(M² × N), где M — длина слова, N — количество слов
  • Память: O(M × N)

#2. Perfect Squares (LeetCode 279) 🟦 Medium

Ссылка: https://leetcode.com/problems/perfect-squares/

Условие: Дано целое число n. Верните минимальное количество perfect square чисел (1, 4, 9, 16, ...), сумма которых равна n.

Примеры:

Ввод: n = 12
Вывод: 3
Объяснение: 12 = 4 + 4 + 4

Ввод: n = 13
Вывод: 2
Объяснение: 13 = 4 + 9

Ограничения:

  • 1 <= n <= 10⁴

💡 Подсказка: Используйте BFS. Каждый уровень представляет количество использованных квадратов.

Решение:

from collections import deque def numSquares(n): squares = [i*i for i in range(1, int(n**0.5) + 1)] queue = deque([n]) level = 0 visited = {n} while queue: level += 1 for _ in range(len(queue)): current = queue.popleft() for sq in squares: if current == sq: return level elif current < sq: break if current - sq not in visited: visited.add(current - sq) queue.append(current - sq) return level

Объяснение:

  • BFS находит минимальное количество шагов
  • Каждый уровень = одно perfect square число
  • visited предотвращает повторную обработку

Сложность:

  • Время: O(n × √n)
  • Память: O(n)

#3. Open the Lock (LeetCode 752) 🟦 Medium

Ссылка: https://leetcode.com/problems/open-the-lock/

Условие: У вас есть замок с 4 круглыми дисками. Каждый диск имеет 10 цифр: '0'-'9'. Диски могут вращаться свободно.

Начальное состояние: '0000'. Дан список deadends — состояний, при которых замок блокируется. Дана цель target.

Верните минимальное количество поворотов для открытия замка или -1, если невозможно.

Примеры:

Ввод: deadends = ["0201","0101","0102","1212","2002"], target = "0202"
Вывод: 6

Ввод: deadends = ["8888"], target = "0009"
Вывод: 1

Ввод: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
Вывод: -1

Ограничения:

  • 1 <= deadends.length <= 500
  • deadends[i].length == 4
  • target.length == 4

💡 Подсказка: Используйте BFS. Из каждого состояния есть 8 переходов (4 позиции × 2 направления).

Решение:

from collections import deque def openLock(deadends, target): deadends = set(deadends) if '0000' in deadends: return -1 queue = deque([('0000', 0)]) visited = {'0000'} while queue: state, steps = queue.popleft() if state == target: return steps # 4 позиции, 2 направления for i in range(4): for d in [-1, 1]: next_digit = (int(state[i]) + d) % 10 next_state = state[:i] + str(next_digit) + state[i+1:] if next_state not in visited and next_state not in deadends: visited.add(next_state) queue.append((next_state, steps + 1)) return -1

Объяснение:

  • BFS находит кратчайший путь
  • 8 переходов из каждого состояния
  • (int(state[i]) + d) % 10 обрабатывает переход 9→0 и 0→9

Сложность:

  • Время: O(10⁴ × 8) = O(10⁴)
  • Память: O(10⁴)

#4. Shortest Path in Binary Matrix (LeetCode 1091) 🟦 Medium

Ссылка: https://leetcode.com/problems/shortest-path-in-binary-matrix/

Условие: Дана квадратная бинарная матрица n x n. Найдите кратчайший путь от левого верхнего угла (0,0) до правого нижнего (n-1, n-1).

Можно двигаться в 8 направлениях (горизонтально, вертикально, диагонально). Все клетки пути должны быть 0.

Примеры:

Ввод: grid = [[0,1],[1,0]]
Вывод: 2

Ввод: grid = [[0,0,0],[1,1,0],[1,1,0]]
Вывод: 4

Ввод: grid = [[1,0,0],[1,1,0],[1,1,0]]
Вывод: -1

Ограничения:

  • n == grid.length == grid[i].length
  • 1 <= n <= 100
  • grid[i][j] — 0 или 1

💡 Подсказка: Используйте BFS с 8 направлениями. Помечайте посещённые клетки, устанавливая grid[r][c] = 1.

Решение:

from collections import deque def shortestPathBinaryMatrix(grid): n = len(grid) # Проверка начала и конца if grid[0][0] or grid[-1][-1]: return -1 queue = deque([(0, 0, 1)]) # (row, col, distance) grid[0][0] = 1 # Помечаем как посещённое directions = [(1,0), (-1,0), (0,1), (0,-1), (1,1), (1,-1), (-1,1), (-1,-1)] while queue: r, c, dist = queue.popleft() if r == n - 1 and c == n - 1: return dist for dr, dc in directions: nr, nc = r + dr, c + dc if 0 <= nr < n and 0 <= nc < n and grid[nr][nc] == 0: grid[nr][nc] = 1 queue.append((nr, nc, dist + 1)) return -1

Объяснение:

  • 8 направлений движения
  • grid[0][0] = 1 помечает посещённые клетки
  • Расстояние включаем в кортеж очереди

Сложность:

  • Время: O(n²)
  • Память: O(n²)

#5. Course Schedule II (LeetCode 210) 🟦 Medium

Ссылка: https://leetcode.com/problems/course-schedule-ii/

Условие: Всего numCourses курсов, пронумерованных от 0 до numCourses - 1. Дан массив prerequisites, где prerequisites[i] = [ai, bi] означает, что для прохождения курса ai нужно сначала пройти курс bi.

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

Примеры:

Ввод: numCourses = 2, prerequisites = [[1,0]]
Вывод: [0,1]

Ввод: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Вывод: [0,1,2,3] или [0,2,1,3]

Ввод: numCourses = 1, prerequisites = []
Вывод: [0]

Ограничения:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= numCourses × (numCourses - 1)

💡 Подсказка: Используйте топологическую сортировку (алгоритм Кана). Подсчитайте indegree для каждого курса и используйте BFS.

Решение:

from collections import deque def findOrder(numCourses, prerequisites): # Строим граф и считаем indegree graph = [[] for _ in range(numCourses)] indegree = [0] * numCourses for course, prereq in prerequisites: graph[prereq].append(course) indegree[course] += 1 # Начинаем с курсов без пререквизитов queue = deque([i for i in range(numCourses) if indegree[i] == 0]) result = [] while queue: course = queue.popleft() result.append(course) for neighbor in graph[course]: indegree[neighbor] -= 1 if indegree[neighbor] == 0: queue.append(neighbor) return result if len(result) == numCourses else []

Объяснение:

  • Топологическая сортировка алгоритмом Кана
  • indegree[i] — количество непроработанных пререквизитов
  • Если результат содержит не все курсы — есть цикл

Сложность:

  • Время: O(V + E)
  • Память: O(V + E)

#6. Шпаргалка

ЗадачаКлючевая идея
Word LadderГенерация 26 вариантов слова
Perfect SquaresBFS по остаткам
Open the Lock8 переходов из состояния
Shortest Path Binary Matrix8 направлений
Course Schedule IIТопологическая сортировка

#7. ⚠️ Common Mistakes

#❌ Ошибка 1: Забыли удалить из wordList

Проблема: В Word Ladder нужно помечать посещённые слова.

# ❌ Неправильно — нет visited if next_word in wordList: queue.append((next_word, steps + 1)) # wordList не изменён — может быть обработан снова! # ✅ Правильно if next_word in wordList: wordList.remove(next_word) # Помечаем как посещённое queue.append((next_word, steps + 1))

Почему это неправильно: Без visited BFS зациклится или будет избыточно работать.


#❌ Ошибка 2: Неправильный переход цифр в Open the Lock

Проблема: Нужно обрабатывать переход 9→0 и 0→9.

# ❌ Неправильно — нет обработки перехода next_digit = int(state[i]) + d # 9 + 1 = 10, а не 0! # ✅ Правильно next_digit = (int(state[i]) + d) % 10 # (9 + 1) % 10 = 0

Почему это неправильно: Цифры на диске цикличны: 9→0 и 0→9.


#❌ Ошибка 3: Забыли проверку начала и конца

Проблема: В Shortest Path нужно проверить, что старт и финиш проходимы.

# ❌ Неправильно — нет проверки queue = deque([(0, 0, 1)]) # ✅ Правильно if grid[0][0] or grid[-1][-1]: return -1 # Начало или конец заблокированы queue = deque([(0, 0, 1)])

Почему это неправильно: Если (0,0) или (n-1,n-1) = 1, пути не существует.


#8. Заключение

BFS: Кратчайший путь — поиск кратчайшего пути в невзвешенном графе.

Ключевые приёмы:

  1. Word Ladder: генерация 26 × length вариантов
  2. Perfect Squares: BFS по остаткам
  3. Open the Lock: 8 переходов (4 позиции × 2 направления)
  4. Course Schedule II: топологическая сортировка (алгоритм Кана)

Далее: Backtracking: Основы