Один шаг при любом размере
O(1) означает константное время: операция выполняется за одно и то же количество шагов, независимо от того, содержит вход 5 элементов или миллион. Объём работы не растёт совсем.
Это лучшая из возможных сложностей. Типичные операции O(1) в TypeScript: чтение элемента массива по индексу, чтение значения Map по ключу, .length, добавление одного элемента в конец и простая арифметика.
Обратите внимание, чего O(1) не означает: это не значит «быстро», это значит «не становится медленнее при росте входных данных». Один константный шаг всё ещё может быть медленным шагом — но он остаётся одним шагом.
Поиск в массиве и в Map
Элемент массива находится в известной позиции в памяти, поэтому words[2] — это один переход: компьютер не проходит по элементам перед ним. То же самое чтение стоит столько же и в массиве из миллиона элементов.
Поиск в Map, например ages.get("Ben"), тоже в среднем занимает константное время: ключ напрямую указывает карте, где хранится значение. Второго возвращаемого значения «был ли он там» нет — get() имеет тип number | undefined и возвращает undefined, когда ключ отсутствует. ages.has("Ben") отвечает на тот же вопрос логическим значением, а ?? 0 превращает отсутствующее значение в значение по умолчанию. Все три операции выполняются за константное время.
Чтение элемента по индексу
Программа читает один элемент из массива из 5 элементов и один из массива в миллион элементов. Оба чтения — это один шаг, длина массива не играет никакой роли.
Вывод: программа на TypeScript и захваченный вывод
const words = ["one", "two", "three", "four", "five"]
const big: number[] = new Array(1000000)
for (let i = 0; i < big.length; i++) {
big[i] = i * 2
}
// По одному шагу на каждое чтение, независимо от длины массива.
console.log(words[2])
console.log(big[999999])
Чтение значения по ключу
ages.get("Ben") сразу находит 25. Отсутствующий ключ "Dan" даёт undefined, а ages.has("Dan") равно false — по-прежнему за константное время. ages.get("Dan") ?? 0 выводит вместо этого 0.
Вывод: программа на TypeScript и захваченный вывод
const ages = new Map<string, number>([
["Ana", 30],
["Ben", 25],
["Cleo", 41],
])
const ben: number | undefined = ages.get("Ben")
console.log(ben, ages.has("Ben"))
const dan: number | undefined = ages.get("Dan")
console.log(dan, ages.has("Dan"))
console.log("значение по умолчанию для отсутствующего ключа:", ages.get("Dan") ?? 0)
Добавление в конец и простая арифметика
push() добавляет один элемент в конец массива. В большинстве случаев это один шаг. (Изредка массив должен вырасти и копируется, но в среднем стоимость одного push остаётся константной.)
Все мелкие операции — присваивания, сложения, сравнения, обмен двух значений — тоже O(1). Это те самые «шаги», в которых считаются все остальные классы сложности.
Добавление одного элемента
colors.push("жёлтый") помещает "жёлтый" в конец. Стоимость не зависит от того, сколько цветов уже находится в массиве.
Вывод: программа на TypeScript и захваченный вывод
const colors = ["красный", "зелёный", "синий"]
console.log("до:", colors, "длина:", colors.length)
colors.push("жёлтый")
console.log("после:", colors, "длина:", colors.length)
Обмен двух значений
[a, b] = [b, a] меняет два значения местами за один шаг константного времени — вспомогательная переменная не нужна. Строка начинается с точки с запятой, чтобы она читалась как отдельная инструкция, а не как индекс к строке выше.
Вывод: программа на TypeScript и захваченный вывод
let a = 1
let b = 2
console.log("до:", a, b)
// Начальная точка с запятой отделяет эту строку от предыдущей.
;[a, b] = [b, a]
console.log("после:", a, b)