Почему TypeScript — идеальный язык для LeetCode?
Если вы до сих пор решали задачи на LeetCode на JavaScript — самое время перейти на TypeScript. Почему? Потому что строгая типизация отсекает целый класс ошибок ещё до запуска кода. Вы не сможете случайно передать строку туда, где ожидается число, а компилятор сам подскажет, какие методы доступны у объекта. Это как ездить на машине с автопилотом — быстрее, безопаснее и приятнее.
LeetCode — это не просто платформа для зубрёжки алгоритмов. Это тренировочный полигон, где вы оттачиваете навыки, которые реально нужны в продакшене. А TypeScript сегодня — стандарт де-факто для enterprise-разработки. Компании вроде Google, Microsoft и Airbnb ищут разработчиков, которые умеют писать типизированный код. Так что, решая задачи на LeetCode на TypeScript, вы убиваете двух зайцев: готовитесь к собеседованию и прокачиваете реальные скиллы.
В этой статье мы разберём, с чего начать, какие типы и структуры данных изучить, и пройдём 3 задачи разного уровня — от лёгкой до сложной. Поехали!
Что нужно знать перед стартом
Прежде чем нырять в пул задач, убедитесь, что у вас есть база. TypeScript — это надстройка над JavaScript, поэтому сначала нужно уверенно владеть JS: замыкания, промисы, методы массивов, работа с объектами. Без этого TypeScript будет казаться просто лишним синтаксическим сахаром.
Основные типы, которые пригодятся на LeetCode
number,string,boolean— база, без них никудаnumber[],string[]— массивы, встречаются в 90% задачRecord<string, number>— объект как словарь (hash map)Map<K, V>— альтернатива объекту с сохранением порядкаSet<T>— для уникальных значенийTuple— кортежи, полезны в задачах на возврат пары значенийnull | undefined— обработка граничных случаев
Структуры данных, которые чаще всего встречаются
- Массивы — основа основ. Двумерные массивы, сортировка, бинарный поиск
- Хеш-таблицы — для быстрого поиска (задача Two Sum — классика)
- Стек и очередь — для задач на скобки, BFS, DFS
- Связные списки — reverse, merge, detect cycle
- Деревья — бинарные, бинарные деревья поиска, обходы
- Графы — обычно на собеседованиях уровня Senior
Не пытайтесь выучить всё сразу. Начните с массивов и хеш-таблиц — это покроет 70% задач уровня Easy и Medium.
Как настроить окружение для TypeScript на LeetCode
LeetCode из коробки поддерживает TypeScript. При выборе языка просто кликните "TypeScript" в дропдауне. Однако если вы хотите писать код локально и тестировать, вот минимальный набор:
npm init -y
npm install typescript @types/node --save-dev
npx tsc --init
Создайте файл solution.ts и запускайте компиляцию командой npx tsc solution.ts && node solution.js. Это поможет вам привыкнуть к строгой типизации и отлавливать ошибки на лету.
Разбор 3 задач на TypeScript: от Easy до Hard
Теперь перейдём к практике. Я выбрал три задачи, которые отлично демонстрируют возможности TypeScript и часто встречаются на собеседованиях.
1. Two Sum (Easy) — классика жанра
Задача: дан массив чисел и цель. Нужно найти два числа, сумма которых равна цели, и вернуть их индексы.
function twoSum(nums: number[], target: number): number[] {
const map = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (map.has(complement)) {
return [map.get(complement)!, i];
}
map.set(nums[i], i);
}
return [];
}
Разбор: Используем Map<number, number> — это типизированная хеш-таблица. Ключ — значение элемента, значение — его индекс. Оператор ! после map.get(complement) — это non-null assertion. Мы уверены, что значение есть, потому что проверили через has. Без него TypeScript ругался бы на возможный undefined.
Временная сложность: O(n), память: O(n). Это оптимальное решение.
2. Valid Parentheses (Medium) — работа со стеком
Задача: дана строка, содержащая скобки (), [], {}. Нужно проверить, корректно ли они закрыты.
function isValid(s: string): boolean {
const stack: string[] = [];
const map: Record<string, string> = {
')': '(',
']': '[',
'}': '{'
};
for (const char of s) {
if (char in map) {
const top = stack.pop() || '#';
if (top !== map[char]) return false;
} else {
stack.push(char);
}
}
return stack.length === 0;
}
Разбор: Используем Record<string, string> для маппинга закрывающих скобок на открывающие. Стек хранит только открывающие скобки. Если встречаем закрывающую — проверяем, совпадает ли верхушка стека с ожидаемой парой. Если нет — строка невалидна.
Тип Record<string, string> — это встроенный утилитарный тип TypeScript, который создаёт объект с динамическими ключами. Он идеально подходит для таких словарей.
Временная сложность: O(n), память: O(n) в худшем случае (если все скобки открывающие).
3. Binary Tree Maximum Path Sum (Hard) — рекурсия с типами
Задача: найти максимальную сумму пути в бинарном дереве. Путь может начинаться и заканчиваться в любых узлах.
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
this.val = (val === undefined ? 0 : val);
this.left = (left === undefined ? null : left);
this.right = (right === undefined ? null : right);
}
}
function maxPathSum(root: TreeNode | null): number {
let maxSum = -Infinity;
function dfs(node: TreeNode | null): number {
if (node === null) return