В нашей новой задаче - 1765. Map of Highest Peak продолжим закреплять работу с семейством простых графовых алгоритмов.
📜 Описание задачи
Вам дана матрица isWater
размером m×n
, где:
isWater[i][j] == 1
указывает, что клетка — это вода.
isWater[i][j] == 0
указывает, что клетка — это суша.
Требуется назначить высоты каждой клетке таким образом, чтобы:
- Высота каждой клетки была неотрицательной.
- Высота любой клетки с водой была равна 0.
- Абсолютная разница высот у соседних клеток не превышала 1.
- Максимальная высота в назначенной карте была как можно больше.
💡 Идея
Мы используем поиск в ширину с несколькими источниками (multi-source BFS), начиная с клеток воды (высота 0
).
На каждом шаге ближайшие клетки суши получают высоту на 1
больше текущей.
Этот метод гарантирует, что все клетки суши получают наилучшую из возможных высот, что приводит к максимизации самой высокой высоты в матрице.
🛠 Подробности подхода
- Инициализация:
- Создаём очередь и добавляем в неё все клетки воды, помечая их высотой
0
.
- Все клетки суши помечаем как
UNVISITED
.
- BFS для расчёта высот:
- Извлекаем клетку из очереди.
- Для всех соседей проверяем, находятся ли они в пределах матрицы и не были ли посещены.
- Если соседняя клетка не посещена, обновляем её высоту и добавляем в очередь.
- Возврат результата:
- После завершения
BFS
возвращаем матрицу с рассчитанными высотами.
⏱ Асимптотика
- Временная сложность:
O(m×n)
— каждая клетка посещается ровно один раз.
- Пространственная сложность:
O(m×n)
— для хранения карты высот и очереди BFS
.
📜 Исходный код
use std::collections::VecDeque;
// Manages BFS logic, including queue operations and height map updates.
struct BFSStrategy<'a> {
queue: &'a mut VecDeque<(usize, usize)>,
height_map: &'a mut Vec<Vec<i32>>,
rows: i32, cols: i32,
}
impl Solution {
pub fn highest_peak(is_water: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let m = is_water.len();
let n = is_water[0].len();
let mut height_map = vec![vec![BFSStrategy::UNVISITED; n]; m];
let mut queue = VecDeque::new();
// Add water cells to the queue and initialize their height to 0.
for row in 0..m {
for col in 0..n {
if is_water[row][col] == 1 {
height_map[row][col] = 0;
queue.push_back((row, col));
}
}
}
let mut bfs = BFSStrategy {
queue: &mut queue,
height_map: &mut height_map,
rows: m as i32, cols: n as i32,
};
// Perform BFS to compute heights for all cells.
while let Some((row, col)) = bfs.queue.pop_front() {
let current_height = bfs.height_map[row][col];
bfs.enqueue(row as i32 + 1, col as i32, current_height + 1);
bfs.enqueue(row as i32 - 1, col as i32, current_height + 1);
bfs.enqueue(row as i32, col as i32 + 1, current_height + 1);
bfs.enqueue(row as i32, col as i32 - 1, current_height + 1);
}
height_map
}
}
impl<'a> BFSStrategy<'a> {
/// Adds a cell to the queue if it's valid and unvisited.
fn enqueue(&mut self, row: i32, col: i32, height: i32) {
if (0..self.rows).contains(&row) && (0..self.cols).contains(&col) {
let row = row as usize;
let col = col as usize;
if self.height_map[row][col] == Self::UNVISITED {
self.height_map[row][col] = height;
self.queue.push_back((row, col));
}
}
}
const UNVISITED: i32 = -1; // Marks cells that haven't been processed.
}
Tags: #rust #algorithms #maps #bfs