главная новое лучшее написать
3

Очередная наша задача - 2471. Minimum Number of Operations to Sort a Binary Tree by Level

🚀 Описание задачи

Дано бинарное дерево. На каждом уровне дерева нужно отсортировать значения узлов в строго возрастающем порядке, минимизируя количество операций. За одну операцию можно поменять значения двух узлов одного уровня местами.

🧠 Идея

Для решения задачи:
1. Выполним обход дерева по уровням и соберем значения узлов для каждого уровня.
2. Для каждого уровня определим минимальное количество перестановок, необходимых для сортировки значений, используя алгоритм обнаружения циклов.

📋 Подробности подхода

  1. Сбор уровней:
    • Используем std::iter::successors для выполнения обхода дерева по уровням.
    • На каждом шаге собираем значения текущего уровня и формируем следующий уровень из дочерних узлов.
  2. Минимальные перестановки:
    • Для каждого уровня создаем массив индексов, отсортированный по значениям.
    • Используя алгоритм обнаружения циклов, подсчитываем минимальное количество операций для приведения массива к упорядоченному состоянию.
  3. Подсчет результата:
    • Суммируем количество перестановок для всех уровней.

⏱️ Асимптотика

💻 Исходный код

// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
//   pub val: i32,
//   pub left: Option<Rc<RefCell<TreeNode>>>,
//   pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//

use std::rc::Rc;
use std::cell::RefCell;

impl Solution {
    /// Returns the minimum number of operations to make each level of the binary tree sorted.
    pub fn minimum_operations(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
        let levels = Self::fill_levels(root);
        levels.into_iter().map(Self::count_swaps).sum()
    }

    /// Collects node values level by level using `std::iter::successors`.
    fn fill_levels(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Vec<i32>> {
        std::iter::successors(
            root.map(|node| vec![node]), // Start with the root node.
            |current_level| {
                let mut next_level = Vec::new();
                for node in current_level {
                    let node = node.borrow();
                    // Add left and right children of the current node to the next level.
                    if let Some(left) = &node.left {
                        next_level.push(left.clone());
                    }
                    if let Some(right) = &node.right {
                        next_level.push(right.clone());
                    }
                }
                // Continue with the next level if it's not empty.
                (!next_level.is_empty()).then(|| next_level)
            },
        )
        .map(|level| {
            // Extract values from the nodes at the current level.
            level.into_iter().map(|node| node.borrow().val).collect()
        })
        .collect()
    }

    /// Calculates the minimum swaps to sort an array using cycle detection.
    fn count_swaps(vals: Vec<i32>) -> i32 {
        let mut indices: Vec<_> = (0..vals.len()).map(Some).collect();
        // Sort indices based on the values they point to.
        indices.sort_by_key(|&i| vals[i.unwrap()]);

        let mut swaps = 0;
        for i in 0..vals.len() {
            if let Some(mut j) = indices[i] {
                indices[i] = None; // Mark the index as visited.
                while let Some(next) = indices[j] {
                    indices[j] = None;
                    j = next; 
                    swaps += 1; // Increment swaps for each step in the cycle.
                }
            }
        }
        swaps
    }
}