Введение в префиксные суммы 0:09 Лекция посвящена префиксным суммам и методу двух указателей. Префиксные суммы полезны для аналитики, особенно для подсчёта событий за определённый интервал времени.
Определение префиксных сумм 0:20 Префиксные суммы позволяют быстро подсчитывать сумму элементов на полуинтервалах. В Python часто используются полуинтервалы, поэтому рассматривается их применение. Для быстрого ответа на запросы необходимо предварительно подсчитать массив префиксных сумм.
Построение массива префиксных сумм 1:39 Длина массива префиксных сумм на один больше длины исходного массива. Элемент массива префиксных сумм содержит сумму всех чисел из исходного массива с индексами от 0 до текущего индекса минус один. Пример: в префиксной сумме 1 лежит число 5, в префиксной сумме 0 — ноль, в префиксной сумме 2 — число 8, сумма чисел 3 и 5.
Метод вычисления префиксных сумм 2:43 Префиксную сумму можно вычислить, добавляя очередной элемент к предыдущей префиксной сумме. Пример: складывание 5 и 0 даёт 5, складывание 5 и 3 даёт 8.
Ошибки при работе с префиксными суммами 3:33 Важно помнить, что массив префиксных сумм должен быть на один больше исходного массива. Ошибка выхода за пределы массива может привести к непредсказуемым последствиям. Переполнение может произойти при работе с большими числами в языках программирования с ограниченными типами данных.
Решение запросов с помощью префиксных сумм 8:02 Для ответа на запрос нужно вычесть префиксную сумму с правой границы запроса из префиксной суммы с левой границы. Пример: из 21 вычесть 8 даёт 13. Полуинтервалы позволяют избежать проблемы с запросами, прижатыми к левому краю.
Оптимизация кода 11:15 На языках без компиляторной оптимизации вызовы функций могут замедлять решение. Вместо вызовов функций можно использовать выражения для ускорения работы. Компиляторы с оптимизацией могут автоматически оптимизировать код.
Применение префиксных сумм в аналитике 12:27 Пример применения: подсчёт количества посетителей сайта за определённый интервал времени. Каждый посетитель приносит единицу посещения, и можно подсчитать количество посетителей за каждый день. Построение массива префиксных сумм позволяет быстро отвечать на запросы о посещаемости.
Задача о подсчёте нулей на полуинтервале 13:27 Дана последовательность чисел и запросы к ней. Задача: подсчитать количество нулей на полуинтервале от i до r, где i не включительно. Простое решение: перебрать все числа и подсчитать нули. Сложность: O(n) для каждого запроса.
Применение префиксных сумм 14:48 Вместо префиксной суммы считаем количество нулей на префиксе. Пример: массив префиксных нулей для последовательности. Вычитание префиксных сумм для ответа на запрос. Сложность: O(n) на построение массива.
Задача о отрезках с нулевой суммой 17:06 Дана последовательность чисел, нужно найти количество отрезков, сумма на которых равна нулю. Пример применения: анализ доходности акций. Наивное решение: перебрать левую и правую границы, суммировать элементы между ними. Сложность: O(n³).
Оптимизация наивного решения 18:58 Фиксируем левую границу и двигаемся направо, прибавляя очередное число к текущей сумме. Если сумма равна нулю, увеличиваем счётчик. Сложность: O(n²).
Нормальное решение с префиксными суммами 21:00 Считаем массивы префиксных сумм. Если суммы в двух местах массива совпадают, между ними сумма равна нулю. Используем словарь для подсчёта количества появлений префиксных сумм. Сложность: O(n).
Преимущества использования словаря 25:36 Словарь эффективен для больших префиксных сумм. Массив неэффективен из-за неизвестного размера.
Задача с двумя указателями 26:23 Дана отсортированная последовательность чисел и число k. Нужно найти количество пар, разность в которых больше k. Пример: последовательность 1, 3, 7, 8, k = 4. Подходящие пары: 1-7, 1-8, 3-8. Ответ: 3 пары.
Введение в задачу 27:41 Обсуждение ситуации, когда после курса по алгоритмам решение задачи кажется очевидным, но интуиция подсказывает, что оно не соответствует ожиданиям. Подчёркивание важности наличия хоть какого-то решения, даже если оно не идеально.
Описание решения 28:20 Перебор всех пар чисел и проверка условия: разница между числами должна быть больше k. Использование упорядоченности массива для эффективного перебора.
Особенности правильного решения 29:14 Правильное решение может быть длиннее неправильного, но оно более эффективно. Пример с массивом {1, 3, 7, 8} и k = 4 иллюстрирует принцип работы.
Принцип работы с указателями 30:11 Фиксация левого числа и переборка правого до первого подходящего числа. При обнаружении подходящего числа добавление его к ответу без перебора остальных.
Вторая хитрость 31:58 При переходе к следующему числу правый указатель двигается с текущего положения. Если число не подходит для текущего левого числа, оно не подходит и для следующего.
Реализация алгоритма 33:09 Левый указатель двигается на единицу, правый — до первого подходящего числа. Проверка условий выхода за пределы массива и добавление длины подходящего хвоста к ответу.
Важность тестирования 35:31 Необходимость тестирования программы на худший случай. Оптимизации могут замедлить программу, поэтому важно учитывать все аспекты.
Заключение 36:46 Подчёркивание важности экспериментов на реальных данных для оценки эффективности оптимизаций. Упоминание о различных способах движения двух указателей в зависимости от задачи.
Задача про игроков 36:59 Необходимо сформировать команду из игроков, у каждого из которых есть число, отражающее его профессионализм. Команда должна быть сплочённой: два самых слабых игрока в сумме играют не хуже, чем самый сильный. Цель — найти самую сильную и сплочённую команду.
Сортировка игроков 37:40 Игроки сортируются по возрастанию профессионализма. В реальной задаче нужно также указать номера игроков.
Формирование команды 38:38 Выбираем самого сильного игрока и формируем команду, добавляя всех подходящих игроков. Если профессионализм игрока отрицательный, его не берём в команду.
Принцип сплочённости 39:38 Сплочённая команда характеризуется умением играть самого слабого игрока. После выбора самого слабого игрока добавляем всех промежуточных игроков.
Использование двух указателей 40:46 Перебираем самого сильного игрока, двигая левый указатель до тех пор, пока сумма умений двух самых слабых игроков больше, чем у самого сильного. Если сумма меньше, не добавляем игрока.
Переложение на классическую форму 42:41 Определяем команду самым слабым игроком, используя два указателя. Левый указатель берёт следующего по силе игрока, правый указатель двигает до упора.
Аккуратность в реализации 44:06 Важно учитывать случаи, когда команда схлопывается до одного человека. Необходимо аккуратно работать с индексами, чтобы избежать выхода за пределы массива.
Слияние отсортированных последовательностей 46:07 Задача: слить две отсортированные последовательности в одну. Используем два указателя: один для первой последовательности, другой для второй. Выводим элементы из обеих последовательностей, сравнивая их по указателям.
Реализация слияния последовательностей 47:30 Идея слияния последовательностей проста, но реализация сложна из-за множества проверок. Стандартные реализации могут быть длинными, но быстрыми. Предлагаемая реализация короче, но медленнее.
Псевдобесконечность в алгоритме 48:26 Создаётся список для ответа и устанавливаются указатели на ноль. Вводится псевдобесконечность для предотвращения ситуаций, когда одна из последовательностей заканчивается. Бесконечность вычисляется как максимальное число из двух последовательностей плюс единица.
Проблемы с текущей реализацией 50:14 Код не очень понятен и требует много времени для осмысления. Решение может не работать с неизменяемыми объектами, такими как строки или кортежи.
Более понятная реализация 51:14 Выделяется память под две слитые последовательности, устанавливаются указатели на ноль. Проверяется, что первая последовательность не закончилась и либо вторая закончилась, либо нужно взять меньшее число из первой. Если первая последовательность закончилась или во второй последовательности меньшее число, берётся из второй.
Вопросы и ответы 53:06 Вопрос о достаточности курса для собеседования: зависит от математической культуры и опыта программирования. Для успешной работы с большими данными необходимы алгоритмы, такие как префиксная сумма.
Префиксная сумма и подсчет отрезков 55:52 Объяснение использования единицы в префиксной сумме для корректного подсчета отрезков с суммой ноль. Пример с отрезком «три минус три» показывает, что без единицы в префиксной сумме можно допустить ошибку.
Правила для переменных-счётчиков 56:06 Вопрос о общепринятых правилах для названия переменных-счётчиков остаётся открытым.
Названия переменных 57:05 Программы автора не являются образцом для именования переменных. Требования к именованию переменных меняются в зависимости от команды. Компромисс между длиной и осмысленностью имён переменных.
Использование break и continue 58:13 Break и continue могут нарушать логику программы. Много брейков в цикле могут указывать на проблемы в коде. В учебных задачах использование брейков может замедлить программу.
Решение третьей задачи 59:39 Объяснение работы алгоритма за O(n). Левый указатель перебирает все элементы цикла. Правый указатель двигается только вправо, что ограничивает количество действий.
Сортировка данных 1:01:46 Данные для задачи про футболистов нужно отсортировать заранее. Стандартная сортировка даёт сложность O(n log n).
Алгоритмы и структуры данных 1:02:14 Список алгоритмов доступен на странице курса. Разделяй и властвуй и динамическое программирование не будут изучаться в явном виде. Курс охватывает полезные алгоритмы для широкого круга задач.
Сложность работы словарей 1:04:30 Словари работают в среднем за O(1) при равномерном распределении данных. Подробнее о работе словарей можно узнать в лекциях о множествах.