Minimum Number of Operations to Sort a Binary Tree by Level

Updated on 17 June, 2025
Minimum Number of Operations to Sort a Binary Tree by Level header image

Problem Statement

You are provided with the root node of a binary tree where each node contains a unique value. The objective is to determine the minimum number of operations required to sort the values of nodes at each level of the tree into strictly increasing order. An operation consists of swapping the values of any two nodes that exist at the same level within the tree. The level of a node is determined by the count of edges between the node and the root of the tree.

Examples

Example 1

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

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

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, 105].
  • 1 <= Node.val <= 105
  • All the values of the tree are unique.

Approach and Intuition

When trying to sort the values in strictly increasing order at each level of the binary tree, the core steps to consider can be derived from the examples given:

  1. Traverse the tree to collect all values level by level.

    • For instance, for a tree structured as [1,4,3,7,6,8,5,...], the first level value is [1], the second level values are [4,3], and so forth.
  2. For each level's list of values:

    • Calculate how many swaps are required to sort that list in ascending order. This can be thought of similarly to determining the number of swaps needed in bubble sort but optimized with better sorting algorithms.

    • Repeat this for every level.

  3. Sum up the required swaps for each level to get the total minimum number of operations needed.

From the example details:

  • Example 1: Swapping is required at the second and third levels of the tree values. Initially, [4,3] requires one swap to become [3,4]. The subsequent values [7,6,8,5] require additional swaps to order them into [5,6,7,8].

  • Example 2: Similar to Example 1, swaps are needed at both the second and third levels. [3,2] becomes [2,3] with one swap and [7,6,5,4] requires multiple steps to rearrange into [4,5,6,7].

  • Example 3: Here, no swaps are necessary as all levels are already in strictly increasing order, resulting in zero operations.

The strategy implicates that understanding the initial order of nodes at each tree level and the number of swaps needed to sort them gives a direct answer to the problem. Each swap represents a unit operation, and the aim is to minimize these across all levels combined.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
    const int BIT_SHIFT = 20; // Configure number of bits to shift
    const int BIT_MASK = 0xFFFFF; // Mask to extract the lower bits

public:
    int minOperations(TreeNode* root) {
        queue<TreeNode*> nodeQueue;
        nodeQueue.push(root);
        int numberOfSwaps = 0;

        while (!nodeQueue.empty()) {
            int sizeOfLevel = nodeQueue.size();
            vector<long long> encodedNodes(sizeOfLevel);

            for (int idx = 0; idx < sizeOfLevel; idx++) {
                TreeNode* currentNode = nodeQueue.front();
                nodeQueue.pop();
                encodedNodes[idx] = (static_cast<long long>(currentNode->val) << BIT_SHIFT) + idx;

                if (currentNode->left) nodeQueue.push(currentNode->left);
                if (currentNode->right) nodeQueue.push(currentNode->right);
            }

            sort(encodedNodes.begin(), encodedNodes.end()); // Sort by the nodes' values

            for (int idx = 0; idx < sizeOfLevel; idx++) {
                int originalPosition = static_cast<int>(encodedNodes[idx] & BIT_MASK);
                if (originalPosition != idx) {
                    swap(encodedNodes[idx], encodedNodes[originalPosition]);
                    numberOfSwaps++;
                    idx--; // recheck current position
                }
            }
        }
        return numberOfSwaps;
    }
};

This C++ solution involves calculating the minimum number of operations needed to sort a binary tree by its levels. The process leverages a breadth-first search (BFS) strategy combined with sorting and encoding techniques to track and minimize the swap operations required to order the tree's values level-by-level.

  • Start by defining constants BIT_SHIFT and BIT_MASK used for encoding the node values.
  • Define a function minOperations taking the root of the tree as its parameter.
    • Initialize a queue to facilitate BFS traversal and a counter numberOfSwaps for tracking the number of operations.
    • Perform BFS:
      1. Retrieve the size of the current level.
      2. Encode each node value shifted left by BIT_SHIFT and combined with its index at the current level. This creates a unique long integer representing both value and position.
      3. Push the children of the current node to the queue for the next level of processing.
      4. Sort the encoded values to determine the desired order by node value.
      5. Check each node's position after sorting against its original index:
      • If a mismatch is found (indicating a required swap), perform the swap and adjust numberOfSwaps.
      • Decrement the index to recheck the current position after swapping.
  • Finally, return the total count of swap operations needed (numberOfSwaps) to achieve a level-by-level ordered tree.

This approach efficiently organizes a binary tree into a sequence where each level is sorted according to the node values, using BFS for traversal and encoding to handle node value-position correlations effectively. The main computational tasks are the sort operation and the swaps needed to align each level's order.

java
class Solution {

    // Constants for encoding data
    final int ENCODE_SHIFT = 20;
    final int ENCODE_MASK = 0xFFFFF;

    public int countMinimumSwaps(TreeNode root) {
        Queue<TreeNode> nodeQueue = new LinkedList();
        nodeQueue.add(root);
        int totalSwaps = 0;

        // Level order traversal using BFS
        while (!nodeQueue.isEmpty()) {
            int countLevel = nodeQueue.size();
            long[] encodedNodes = new long[countLevel];

            // Encode node values
            for (int i = 0; i < countLevel; i++) {
                TreeNode currentNode = nodeQueue.poll();
                // Encode: higher bits for value, lower for index
                encodedNodes[i] = ((long) currentNode.val << ENCODE_SHIFT) + i;

                if (currentNode.left != null) nodeQueue.add(currentNode.left);
                if (currentNode.right != null) nodeQueue.add(currentNode.right);
            }

            // Sorting by node value using encoded data
            Arrays.sort(encodedNodes);

            // Correct the positions
            for (int i = 0; i < countLevel; i++) {
                int originalIndex = (int) (encodedNodes[i] & ENCODE_MASK);
                if (originalIndex != i) {
                    // Swap operations
                    long swapTemp = encodedNodes[i];
                    encodedNodes[i--] = encodedNodes[originalIndex]; // re-check current after swap
                    encodedNodes[originalIndex] = swapTemp;
                    totalSwaps++;
                }
            }
        }
        return totalSwaps;
    }
}

This Java solution is aimed at determining the minimal number of operations required to sort a binary tree by levels using a BFS (Breadth-First Search) approach. Here’s how the solution works step-by-step:

  1. Initialize a queue to manage the tree nodes level-by-level and add the root node to the queue.

  2. Define a variable to keep track of the total number of swap operations required.

  3. Use a while loop to process the nodes until no nodes are left in the queue:

    • For each level, get the number of nodes (countLevel) at that level and create an array to keep track of these nodes' values encoded with their indices.

    • Traverse each node, remove it from the queue, and:

      • Encode each node by shifting its value and adding its index in the array.
      • Add the node’s children to the queue for further processing.
    • After processing all nodes at a level, sort the encoded array.

    • Analyze the sorted positions and perform swaps whenever the index does not match the intended position. Recalculate the index, and for each misplacement, increase the swap count.

  4. After all levels are processed, return the count of swaps as the result.

The solution efficiently uses BFS to traverse each level, employing an array to manage the sorting and reordering of node positions at each level to determine the number of swaps, ensuring the tree gets sorted with minimal operations. This requires understanding of binary tree operations, BFS traversal, bit manipulation for efficient encoding, and basic array manipulations.

python
class Solution:
    # Bit manipulation constants
    BITS = 20
    FILTER = 0xFFFFF

    def minOperations(self, rootNode: Optional["TreeNode"]) -> int:
        queue = deque([rootNode])
        total_swaps = 0

        while queue:
            level_length = len(queue)
            encoded_nodes = []

            for pos in range(level_length):
                current_node = queue.popleft()
                encoded_nodes.append((current_node.val << self.BITS) + pos)

                if current_node.left:
                    queue.append(current_node.left)
                if current_node.right:
                    queue.append(current_node.right)

            encoded_nodes.sort()

            idx = 0
            while idx < level_length:
                original_index = encoded_nodes[idx] & self.FILTER
                if original_index != idx:
                    encoded_nodes[idx], encoded_nodes[original_index] = encoded_nodes[original_index], encoded_nodes[idx]
                    total_swaps += 1
                    idx -= 1
                idx += 1

        return total_swaps

The Python3 solution focuses on determining the minimum number of operations needed to sort a binary tree by level. The approach utilizes a breadth-first search (BFS) strategy to traverse the tree and sort nodes at each level based on their values.

  • Begin by initializing a queue with the root node. Use this queue to explore the tree level by level.
  • Track the total number of swaps required with a total_swaps variable initialized at zero.
  • As you traverse each level:
    • For each node at the current level, encode the node value combined with its position using bit manipulation. This encoding is crucial to keep the original index of each node.
    • After encoding all nodes at the current level, sort the list of encoded nodes based on values.
    • Use a while loop to determine and count the required swaps for sorting the nodes to their rightful positions based on the original indices. The sorting ensures nodes are in ascending order.
    • Adjust the queue by appending the left and right children of each node to handle the next level in subsequent iterations.

The encoded index aids in efficient sorting and tracking of node positions, allowing for an effective swap count. At the end of the BFS traversal, total_swaps contains the minimum operations required to sort the tree by its levels. This method optimizes the sorting operations while ensuring that the tree's level order properties are maintained. The function finally returns the count of these operations.

Comments

No comments yet.