Ответ
Амортизированная сложность — O(1).
Объяснение:
- Обычный случай (O(1)): Если во внутреннем массиве есть свободная емкость (
size < capacity), элемент просто помещается в следующую ячейку. - Случай расширения (O(n)): Если массив заполнен, происходит реаллокация: создается новый массив большего размера (обычно
capacity * 1.5), и все существующие элементы копируются в него. Эта операция имеет сложность O(n).
Так как дорогостоящее расширение происходит редко, средняя стоимость добавления одного элемента (амортизированная) остается константной — O(1).
Пример:
ArrayList<Integer> list = new ArrayList<>(3); // capacity = 3
list.add(1); // O(1)
list.add(2); // O(1)
list.add(3); // O(1)
list.add(4); // O(n) - происходит расширение массива и копирование 3 элементов
// Последующие добавления снова будут O(1), пока не заполнится новая capacity. Ответ 18+ 🔞
Так, слушай, про эту вашу амортизированную сложность O(1) в ArrayList.add(). Ну, это ж классика, блядь, ёпта! Сейчас на пальцах, как для дебила, объясню.
Представь себе, у тебя есть стакан. Ты в него по капле воду льешь. Пока не полный — просто льешь, нихуя не делаешь. Это наш обычный случай, O(1). Быстро и без напряга.
А теперь стакан полный. Ты такой: "Опа, блядь, переполнение!" Тебе нужен стакан побольше. Ты бежишь на кухню, ищешь новый, переливаешь всю воду из старого в новый. Это операция, сука, O(n) — потому что каждую каплю, каждую хуйню надо перенести. Долго, муторно, в рот меня чих-пых!
Но! Ты же не будешь после каждой капли новый стакан искать? Нет, блядь. Ты нальёшь большой стакан, и потом снова долго-долго просто льешь, пока он не заполнится. Дорогая операция (поиск и перелив) была РЕДКОЙ. А в среднем, на каждую твою каплю, времени ушло — копейки. Вот это и есть амортизированная O(1). В среднем — быстро, ёбана!
Вот смотри на код, тут всё честно:
ArrayList<Integer> list = new ArrayList<>(3); // capacity = 3
list.add(1); // O(1) — налил каплю
list.add(2); // O(1) — налил каплю
list.add(3); // O(1) — налил каплю
list.add(4); // O(n) — ОЙ БЛЯ! Стакан полный! Бегу за новым, переливаю три старых элемента!
// А дальше опять O(1), пока новый большой стакан не заполнится.
Вот и весь сказ, блядь. Хитрость в том, что новый стакан берут обычно в полтора раза больше (capacity * 1.5). Поэтому эти мучительные расширения происходят всё реже и реже. И в итоге, если ты добавляешь овердохуища элементов, средняя цена за один добавленный элемент — константа. O(1) и всё тут.
А если кто-то говорит, что add всегда O(n) — тот, извини, просто мудак, который не вник. Он видел только момент, когда Герасим топит Муму, а про то, как они до этого счастливо жили, — забыл.