Задача
Напишите оптимальный класс PaginationHelper для постраничной навигации по коллекции.
class PaginationHelper {
constructor(collection, itemsPerPage) {}
itemCount() {} // всего элементов
pageCount() {} // всего страниц
pageItemCount(pageIndex) {} // элементов на странице, -1 если вне диапазона
pageIndex(itemIndex) {} // на какой странице элемент, -1 если вне диапазона
}Пример
const helper = new PaginationHelper(['a', 'b', 'c', 'd', 'e', 'f'], 4);
helper.itemCount(); // 6
helper.pageCount(); // 2
helper.pageItemCount(0); // 4
helper.pageItemCount(1); // 2 (последняя страница неполная)
helper.pageItemCount(2); // -1 (страницы нет)
helper.pageIndex(5); // 1
helper.pageIndex(2); // 0
helper.pageIndex(-1); // -1
helper.pageIndex(20); // -1Решение
Оптимальное решение
// Все методы — O(1). Храним только длину коллекции и размер страницы, // всё остальное вычисляется арифметически, без прохода по данным. class PaginationHelper { constructor(collection, itemsPerPage) { this._count = collection.length; this._itemsPerPage = itemsPerPage; // ceil, чтобы неполная последняя страница тоже считалась this._pages = Math.ceil(this._count / itemsPerPage); } itemCount() { return this._count; } pageCount() { return this._pages; } pageItemCount(pageIndex) { if (pageIndex < 0 || pageIndex >= this._pages) return -1; // Последняя страница может быть неполной const isLast = pageIndex === this._pages - 1; if (!isLast) return this._itemsPerPage; const remainder = this._count % this._itemsPerPage; return remainder === 0 ? this._itemsPerPage : remainder; } pageIndex(itemIndex) { if (itemIndex < 0 || itemIndex >= this._count) return -1; return Math.floor(itemIndex / this._itemsPerPage); } }
Наивное решение (хранит нарезанные страницы)
// O(n) память и время в конструкторе — материализует все страницы. // Избыточно: те же ответы получаются арифметически за O(1). class PaginationHelper { constructor(collection, itemsPerPage) { this.pages = []; for (let i = 0; i < collection.length; i += itemsPerPage) { this.pages.push(collection.slice(i, i + itemsPerPage)); } this.collection = collection; this.itemsPerPage = itemsPerPage; } itemCount() { return this.collection.length; } pageCount() { return this.pages.length; } pageItemCount(pageIndex) { return this.pages[pageIndex]?.length ?? -1; } pageIndex(itemIndex) { if (itemIndex < 0 || itemIndex >= this.collection.length) return -1; return Math.floor(itemIndex / this.itemsPerPage); } }