Скользящее окно
Максимальная сумма различных подмассивов длины k
Найти максимальную сумму подмассива длины k с различными элементами
Постановка задачи
Описание (LeetCode - 2461. Maximum Sum of Distinct Subarrays With Length K)
Дан целочисленный массив nums и число k. Нужно найти максимальную сумму
подмассива длины k, в котором все элементы различны.
Если такого подмассива нет, нужно вернуть 0.
Пример 1:
nums = [1, 5, 4, 2, 9, 9, 9], k = 3
Результат:
15
Пояснение:
Подмассивы длины 3 с различными элементами: [1, 5, 4], [5, 4, 2],
[4, 2, 9]. Максимальную сумму дает [4, 2, 9]: 15.
Пример 2:
nums = [4, 4, 4], k = 3
Результат:
0
Ограничения:
1 <= k <= nums.length <= 10⁵1 <= nums[i] <= 10⁵
Решение
Здесь окно имеет фиксированную длину k, поэтому сумму можно обновлять так же,
как в задаче о максимальном среднем подмассиве: добавляем новый элемент справа и
убираем старый слева.
Но есть дополнительное условие: все элементы внутри окна должны быть различны. Чтобы проверять это быстро, будем хранить частоты элементов в текущем окне.
Идея решения:
Поддерживаем два значения:
windowSum- сумма элементов текущего окна.counts- частоты элементов текущего окна.
Когда окно достигает размера k, проверяем количество различных элементов. Если
counts содержит ровно k ключей, значит, каждый элемент в окне встречается
один раз. Тогда окно подходит, и можно обновить максимальную сумму.
Если окно длины k содержит ровно k различных элементов, значит, все элементы
в нем уникальны. Это удобнее, чем отдельно искать дубликаты внутри каждого окна.
После проверки сдвигаем окно: перед следующим шагом убираем элемент, который вышел за левую границу.
Основные шаги:
- Инициализируем
windowSum = 0,maxSum = 0и таблицу частот. - Идем правой границей
rightпо массиву. - Добавляем
nums[right]в сумму и таблицу частот. - Если размер окна стал больше
k, убираем элементnums[right - k]. - Когда окно имеет размер
kи количество ключей в таблице равноk, обновляемmaxSum. - Возвращаем
maxSum.
Рассмотрим пример:
nums = [1, 5, 4, 2, 9, 9, 9], k = 3
- Окно
[1, 5, 4], сумма равна10, все элементы различны.
- Окно
[5, 4, 2], сумма равна11, все элементы различны.
- Окно
[4, 2, 9], сумма равна15, все элементы различны. Это текущий максимум.
- Окно
[2, 9, 9], есть повтор9.
- Окно
[9, 9, 9], есть повтор9.
Окна с повторами не подходят. Максимальная сумма среди валидных окон равна
15.
Оценка сложности
Временная сложность
Мы один раз проходим по массиву. Добавление и удаление элемента из хеш-таблицы в
среднем занимают O(1).
Итоговая временная сложность: O(n).
Пространственная сложность
В таблице частот хранится не больше k элементов текущего окна.
Пространственная сложность: O(k).
Код решения
Приведем код решения.
func maximumSubarraySum(nums []int, k int) int64 {
counts := map[int]int{}
var windowSum int64
var maxSum int64
for right := 0; right < len(nums); right++ {
windowSum += int64(nums[right])
counts[nums[right]]++
if right >= k {
leftValue := nums[right-k]
windowSum -= int64(leftValue)
counts[leftValue]--
if counts[leftValue] == 0 {
delete(counts, leftValue)
}
}
if right >= k-1 && len(counts) == k {
maxSum = max(maxSum, windowSum)
}
}
return maxSum
}Итоги
Задача Maximum Sum of Distinct Subarrays With Length K объединяет фиксированное скользящее окно и проверку уникальности через частоты.
- Суть алгоритма: поддерживаем сумму окна длины
kи таблицу частот; если количество различных элементов равноk, обновляем максимальную сумму. - Эффективность:
- Временная сложность:
O(n), потому что каждый элемент один раз добавляется в окно и один раз удаляется из него. - Пространственная сложность:
O(k), так как в таблице хранятся элементы текущего окна.
- Временная сложность:
- Граничные случаи:
- Подходящего окна нет:
maxSumостанется0. k == 1: любой одиночный элемент уникален, ответом будет максимальный элемент массива.- В окне есть повтор: количество различных элементов меньше
k, поэтому окно не учитывается.
- Подходящего окна нет:
- Оптимальное решение: мы не пересчитываем сумму и уникальность каждого окна с нуля, а обновляем оба состояния при каждом сдвиге.