diff --git a/_posts/2024-12-23-LeetCode-2471.md b/_posts/2024-12-23-LeetCode-2471.md new file mode 100644 index 0000000..8c54da2 --- /dev/null +++ b/_posts/2024-12-23-LeetCode-2471.md @@ -0,0 +1,239 @@ +--- +layout: post +title: 逐层排序二叉树所需的最少操作数目 +date: 2024-12-23 17:30:00 +0800 +categories: algorithm +tags: algorithm +published: true +--- + +* content +{:toc} + +## Minimum Number of Operations to Sort a Binary Tree by Level + +[LeetCode 2471](https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/description/){:target="_blank"} + +You are given the root of a binary tree with unique values. + +In one operation, you can choose any two nodes at the same level and swap their values. + +Return the minimum number of operations needed to make the values at each level sorted in a strictly increasing order. + +The level of a node is the number of edges along the path between it and the root node. + +**Example 1:** + +![example-1]({{ '/styles/images/leetcode-2471/example-1.png' | prepend: site.baseurl }}){:width="404" height="auto"} + +``` +Input: root = [1,4,3,7,6,8,5,null,null,null,null,9,null,10] +Output: 3 +Explanation: +- Swap 4 and 3. The 2nd level becomes [3,4]. +- Swap 7 and 5. The 3rd level becomes [5,6,8,7]. +- Swap 8 and 7. The 3rd level becomes [5,6,7,8]. +We used 3 operations so return 3. +It can be proven that 3 is the minimum number of operations needed. +``` + +**Example 2:** + +![example-1]({{ '/styles/images/leetcode-2471/example-2.png' | prepend: site.baseurl }}){:width="293" height="auto"} + +``` +Input: root = [1,3,2,7,6,5,4] +Output: 3 +Explanation: +- Swap 3 and 2. The 2nd level becomes [2,3]. +- Swap 7 and 4. The 3rd level becomes [4,6,5,7]. +- Swap 6 and 5. The 3rd level becomes [4,5,6,7]. +We used 3 operations so return 3. +It can be proven that 3 is the minimum number of operations needed. +``` + +**Example 3:** + +![example-1]({{ '/styles/images/leetcode-2471/example-3.png' | prepend: site.baseurl }}){:width="354" height="auto"} + +``` +Input: root = [1,2,3,4,5,6] +Output: 0 +Explanation: Each level is already sorted in increasing order so return 0. +``` + +**Constraints:** + +* The number of nodes in the tree is in the range [1, $$10^5$$]. +* 1 <= Node.val <= $$10^5$$ +* All the values of the tree are unique. + +## Hash Map + +```kotlin +class Solution { + fun minimumOperations(root: TreeNode?): Int { + if (root == null) return 0 + var operators = 0 + val queue = LinkedList() + queue.offer(root) + + while (queue.isNotEmpty()) { + val size = queue.size + val list = MutableList(size) { 0 } + repeat(size) { + val node = queue.pop() + list[it] = node.`val` + node.left?.apply(queue::offer) + node.right?.apply(queue::offer) + } + operators += minSwaps(list) + } + return operators + } + + fun minSwaps(original: MutableList): Int { + var swaps = 0 + val target = original.sorted() + val value2Index = original.withIndex().associate { Pair(it.value, it.index) }.toMutableMap() + repeat(original.size) { i -> + if (original[i] != target[i]) { + swaps++ + val index = value2Index[target[i]]!! + value2Index[original[i]] = index + original[index] = original[i] + } + } + return swaps + } +} +``` + +## Bit Manipulation + +```kotlin +class Solution { + val shift = 20 + val mask = 1L.shl(shift) - 1 + + fun minimumOperations(root: TreeNode?): Int { + if (root == null) return 0 + var operators = 0 + val queue = LinkedList() + queue.offer(root) + while (queue.isNotEmpty()) { + val size = queue.size + val list = MutableList(size) { 0L } + repeat(size) { + val node = queue.pop() + list[it] = node.`val`.toLong().shl(shift) + it + node.left?.apply(queue::offer) + node.right?.apply(queue::offer) + } + list.sort() + var i = 0 + while (i < list.size) { + val index = list[i].and(mask).toInt() + if (index != i) { + list[i] = list[index].also { list[index] = list[i] } + operators++ + } else i++ + } + } + return operators + } +} +``` + +## Cycle Sort + +```kotlin +class Solution { + fun minimumOperations(root: TreeNode?): Int { + if (root == null) return 0 + var operators = 0 + val queue = LinkedList() + queue.offer(root) + while (queue.isNotEmpty()) { + val size = queue.size + val list = MutableList(size) { 0 } + repeat(size) { + val node = queue.pop() + list[it] = node.`val` + node.left?.apply(queue::offer) + node.right?.apply(queue::offer) + } + operators += cycleSort(list) + } + return operators + } + + fun cycleSort(list: MutableList): Int { + val value2Index = list.withIndex().associate { Pair(it.value, it.index) } + list.sort() + val visited = BooleanArray(list.size) { false } + var ans = 0 + repeat(list.size) { i -> + if (visited[i] || value2Index[list[i]] == i) return@repeat + var j = i + var cycleSize = 0 + while (!visited[j]) { + visited[j] = true + j = value2Index[list[j]]!! + cycleSize++ + } + ans += cycleSize - 1 + } + return ans + } +} +``` + +## Bit Manipulation + Cycle Sort + +```kotlin +class Solution { + val shift = 20 + val mask = 1L.shl(shift) - 1 + + fun minimumOperations(root: TreeNode?): Int { + if (root == null) return 0 + var operators = 0 + val queue = LinkedList() + queue.offer(root) + while (queue.isNotEmpty()) { + val size = queue.size + val list = MutableList(size) { 0L } + repeat(size) { + val node = queue.pop() + list[it] = node.`val`.toLong().shl(shift) + it + node.left?.apply(queue::offer) + node.right?.apply(queue::offer) + } + operators += cycleSort(list) + } + return operators + } + + fun cycleSort(list: MutableList): Int { + list.sort() + val visited = BooleanArray(list.size) { false } + var ans = 0 + repeat(list.size) { i -> + if (visited[i] || list[i].and(mask).toInt() == i) return@repeat + var j = i + var cycleSize = 0 + while (!visited[j]) { + visited[j] = true + j = list[j].and(mask).toInt() + cycleSize++ + } + ans += cycleSize - 1 + } + return ans + } +} +``` + + + \ No newline at end of file diff --git a/styles/images/leetcode-2471/example-1.png b/styles/images/leetcode-2471/example-1.png new file mode 100644 index 0000000..d0ddd7c Binary files /dev/null and b/styles/images/leetcode-2471/example-1.png differ diff --git a/styles/images/leetcode-2471/example-2.png b/styles/images/leetcode-2471/example-2.png new file mode 100644 index 0000000..428c908 Binary files /dev/null and b/styles/images/leetcode-2471/example-2.png differ diff --git a/styles/images/leetcode-2471/example-3.png b/styles/images/leetcode-2471/example-3.png new file mode 100644 index 0000000..5beecc7 Binary files /dev/null and b/styles/images/leetcode-2471/example-3.png differ