LeetCode 2471. Minimum Number of Operations to Sort a Binary Tree by Level in F#

URL

https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/description/?envType=daily-question&envId=2024-12-23

Code

https://github.com/syohex/dotnet-study/blob/master/fsharp/leetcode/challenge/202412/minimum_number_of_operations_to_sort_a_binary_tree_by_level/main.fsx

type Tree =
    | Leaf
    | Node of int * Tree * Tree

let minimumOperations (root: Tree) : int =
    let countSwaps orig =
        let rec countSwaps' sorted i (orig: int[]) origMap acc =
            match sorted with
            | [] -> acc
            | h :: t ->
                if h = orig.[i] then
                    countSwaps' t (i + 1) orig origMap acc
                else
                    let origIndex = Map.find h origMap
                    let origMap = Map.add orig.[i] origIndex origMap
                    let tmp = orig.[i]
                    orig.[i] <- orig.[origIndex]
                    orig.[origIndex] <- tmp
                    countSwaps' t (i + 1) orig origMap (acc + 1)

        let sorted = orig |> List.sort

        let origMap =
            orig |> List.indexed |> List.fold (fun acc (i, v) -> Map.add v i acc) Map.empty

        countSwaps' sorted 0 (List.toArray orig) origMap 0

    let rec minimumOperations' q acc =
        match q with
        | [] -> acc
        | _ ->
            let orig =
                q
                |> List.fold
                    (fun acc node ->
                        match node with
                        | Leaf -> acc
                        | Node(v, _, _) -> v :: acc)
                    []
                |> List.rev

            let q =
                q
                |> List.fold
                    (fun acc node ->
                        match node with
                        | Leaf -> acc
                        | Node(_, left, Leaf) -> left :: acc
                        | Node(_, Leaf, right) -> right :: acc
                        | Node(v, left, right) -> right :: left :: acc)
                    []
                |> List.rev

            let ops = countSwaps orig
            minimumOperations' q (acc + ops)

    minimumOperations' [ root ] 0