Ссылка на задачу — 2780. Minimum Index of a Valid Split.
📘 Описание задачи
- Дан массив целых чисел
nums
, в котором гарантированно существует один доминирующий элемент
(то есть такой элемент, который встречается чаще, чем половина длины массива).
- Необходимо найти наименьший индекс
i
, такой что массив можно разделить на две части:
nums[0],..,nums[i]
и nums[i+1],..,nums[n-1]
,
- и обе части будут иметь одинаковый доминирующий элемент.
- Если такого разделения не существует — вернуть
-1
.
💡 Идея
Для эффективного поиска доминирующего элемента хорошо подходит алгоритм большинства голосов Бойера — Мура.
Зная доминирующий элемент, можно пройти по массиву и в каждой возможной точке разделения отслеживать:
- Сколько раз этот элемент встречался слева;
- Сколько осталось справа;
- Затем проверяется, является ли он доминирующим в обеих частях.
🔍 Детали подхода
- Применяем алгоритм голосования большинства для нахождения доминанты.
- Подсчитываем точное количество его вхождений, чтобы использовать для отслеживания остатка справа.
- Идём по массиву от 1 до n - 1:
- Обновляем количество слева и справа.
- Проверяем условия доминирования в обеих частях:
2 * left_count > left_size
2 * remaining > right_size
- Возвращаем первый подходящий индекс, либо
-1
.
⏱️ Асимптотики
- Время:
O(n)
— три линейных прохода.
- Память:
O(1)
— только счётчики.
🧾 Исходный код
impl Solution {
pub fn minimum_index(nums: Vec<i32>) -> i32 {
let n = nums.len() as i32;
// Find the dominant element and its total count in the array
let (dominant, total_count) = Self::find_dominant(&nums);
// Counters to track dominant element in the left & right subarrays
let mut left_count = 0;
let mut remaining = total_count;
(1..n).find(|&left_size| {
let right_size = n - left_size;
if nums[left_size as usize - 1] == dominant {
left_count += 1;
remaining -= 1;
}
// Check if dominant element is dominant in both subarrays
2 * left_count > left_size && 2 * remaining > right_size
}).unwrap_or(0) - 1
}
/// Returns the dominant element and its total count.
/// Assumes there is exactly one dominant element.
fn find_dominant(nums: &[i32]) -> (i32, i32) {
// Phase 1: Find candidate using Boyer-Moore algorithm
let mut candidate = 0;
let mut freq = 0;
for &num in nums {
if freq == 0 {
candidate = num;
}
freq += if num == candidate { 1 } else { -1 };
}
// Phase 2: Count occurrences of the candidate
let count = nums.iter().filter(|&&x| x == candidate).count() as _;
(candidate, count)
}
}
Tags: #rust #algorithms #dominant #counting