Ссылка на задачу с LeetCode — 2444. Count Subarrays With Fixed Bounds.
📋 Условие задачи
- Дан массив целых чисел
nums
и два целых числа minK
и maxK
.
- Необходимо посчитать количество подотрезков (непрерывных подмассивов), в которых минимальный элемент равен
minK
, а максимальный — maxK
.
Пример:
- Ввод:
nums = [1,3,5,2,7,5], minK = 1, maxK = 5
- Вывод:
2
- Пояснение: Подходящие подотрезки — [1,3,5] и [1,3,5,2].
💡 Идея
- Элементы, выходящие за пределы
[minK, maxK]
, ломают возможность создать валидный подотрезок.
- Поэтому нужно работать только с кусками массива, где все элементы находятся внутри заданных границ.
- В каждом таком куске мы будем отслеживать последние появления
minK
и maxK
и считать количество возможных подотрезков на лету.
🛠️ Детали подхода
- Разбиваем массив на куски (
chunk_by
), где элементы либо все в пределах [minK, maxK]
, либо все вне.
- Для каждого валидного куска (на каждой позиции):
- Запоминаем последние индексы появления
minK
и maxK
.
- Если оба встречались, прибавляем
min(minK_index, maxK_index) + 1
к ответу.
- В конце суммируем количество подотрезков по всем валидным кускам.
⏳ Асимптотика
- Время:
O(n)
, где n
— длина массива nums.
- Каждый элемент обрабатывается не более двух раз (разбиение + подсчёт).
- Память:
O(1)
- Используется только фиксированное число переменных и итераторы.
🧩 Исходный код
impl Solution {
pub fn count_subarrays(nums: Vec<i32>, min_k: i32, max_k: i32) -> i64 {
// Early return if the fixed bounds are invalid
if min_k > max_k {
return 0;
}
// Helper closure to check if a value is within the [min_k, max_k] range
let in_bounds = |value: i32| (min_k..=max_k).contains(&value);
// Split nums into chunks where elements are consistently either in or out of range
nums.chunk_by(|&a, &b| in_bounds(a) == in_bounds(b))
// Count fixed-bound subarrays within each valid chunk
.map(|chunk| Self::count_fixed_bound_subarrays(chunk, min_k, max_k))
// Sum the counts across all chunks
.sum::<usize>() as i64
}
// Counts the number of fixed-bound subarrays inside a valid chunk
fn count_fixed_bound_subarrays(chunk: &[i32], min_k: i32, max_k: i32) -> usize {
let mut min_k_index = None;
let mut max_k_index = None;
chunk.iter().enumerate().map(|(index, &value)| {
// Update the most recent positions of min_k and max_k
if value == min_k {
min_k_index = Some(index);
}
if value == max_k {
max_k_index = Some(index);
}
// The number of valid subarrays ending at `index`
match (min_k_index, max_k_index) {
(Some(min_idx), Some(max_idx)) => min_idx.min(max_idx) + 1,
_ => 0,
}
}).sum()
}
}
Tags: #rust #algorithms #counting