Problem

Given a preorder traversal of a Binary Search Tree (BST), determine the number of elements in the traversal that are less than the root node.

Examples

Example 1

1
2
3
Input: [10, 5, 1, 7, 40, 50]
Output: 3
Explanation: The root is 10. Elements less than 10 are [5, 1, 7].

Example 2

1
2
3
Input: [25, 15, 10, 20, 30, 35, 40]
Output: 3
Explanation: The root is 25. Elements less than 25 are [15, 10, 20].

Solution

Method 1 - Naive

Binary Search Tree (BST) is structured such that:

  • For any node in the tree, all elements in the left subtree are smaller than the node, and all elements in the right subtree are larger than the node.

From the preorder traversal, the first element is always the root. We need to count the elements in the traversal that are less than this root.

Approach

  1. Step 1: Extract the root node as the first element of the preorder list.
  2. Step 2: Iterate through the list and count the elements smaller than the root node.
  3. Output: Return the count of these smaller elements.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {

    public int countElementsLessThanRoot(List<Integer> preorder) {
        // Step 1: Extract the root
        int root = preorder.get(0);

        // Step 2: Count elements less than root
        int count = 0;
        for (int i = 1; i < preorder.size(); i++) {
            if (preorder.get(i) < root) {
                count++;
            }
        }

        return count;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();

        // Example 1
        List<Integer> example1 = List.of(10, 5, 1, 7, 40, 50);
        System.out.println(sol.countElementsLessThanRoot(example1)); // Output: 3

        // Example 2
        List<Integer> example2 = List.of(25, 15, 10, 20, 30, 35, 40);
        System.out.println(sol.countElementsLessThanRoot(example2)); // Output: 3

        // Example 3
        List<Integer> example3 = List.of(40, 30, 20, 35, 50, 60);
        System.out.println(sol.countElementsLessThanRoot(example3)); // Output: 4
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def count_elements_less_than_root(self, preorder):
        # Step 1: Extract the root
        root = preorder[0]
        
        # Step 2: Count elements less than root
        count = sum(1 for x in preorder[1:] if x < root)
        
        return count

# Testing the solution
if __name__ == "__main__":
    solution = Solution()
    
    # Example 1
    example1 = [10, 5, 1, 7, 40, 50]
    print(solution.count_elements_less_than_root(example1))  # Output: 3
    
    # Example 2
    example2 = [25, 15, 10, 20, 30, 35, 40]
    print(solution.count_elements_less_than_root(example2))  # Output: 3

    # Example 3
    example3 = [40, 30, 20, 35, 50, 60]
    print(solution.count_elements_less_than_root(example3))  # Output: 4

Complexity

  • ⏰ Time complexity: O(n), as we iterate through the preorder traversal once to count elements less than the root.
  • 🧺 Space complexity: O(1). No additional data structures are used apart from the input list (in-place computation).

The idea is to employ a modified form of binary search. The steps involve checking the middle element:

  • If it is greater than the root, search the left half of the sorted array.
  • If it is less than the root and the next element is greater, the middle index gives the count of elements less than the root.
  • Otherwise, search the right half.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Solution {
    public int countElementsLessThanRoot(int[] preorder) {
        // Step 1: Extract the root
        int root = preorder[0];
        
        // Step 2: Binary search using BST preorder property
        int low = 0, high = preorder.length - 1;
        while (low < high) {
            int mid = (low + high) / 2;

            // If the mid element is greater than the root, move left
            if (preorder[mid] > root) {
                high = mid - 1;
            } else {
                // If mid element is smaller, move right
                if (mid + 1 < preorder.length && preorder[mid + 1] > root) {
                    return mid + 1;
                }
                low = mid + 1;
            }
        }

        return low; // If no elements are smaller than root
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        
        // Example 1
        int[] example1 = {10, 5, 1, 7, 40, 50};
        System.out.println(sol.countElementsLessThanRoot(example1)); // Output: 3
        
        // Example 2
        int[] example2 = {25, 15, 10, 20, 30, 35, 40};
        System.out.println(sol.countElementsLessThanRoot(example2)); // Output: 3

        // Example 3
        int[] example3 = {40, 30, 20, 35, 50, 60};
        System.out.println(sol.countElementsLessThanRoot(example3)); // Output: 4
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution:
    def countElementsLessThanRoot(self, preorder: list[int]) -> int:
        # Step 1: Extract the root
        root: int = preorder[0]
        
        # Step 2: Binary search using BST preorder property
        low: int = 0
        high: int = len(preorder) - 1
        while low < high:
            mid: int = (low + high) // 2

            # If the mid element is greater than the root, move left
            if preorder[mid] > root:
                high = mid - 1
            else:
                # If mid element is smaller, move right
                if mid + 1 < len(preorder) and preorder[mid + 1] > root:
                    return mid + 1
                low = mid + 1

        return low  # If no elements are smaller than root

# Testing the solution
if __name__ == "__main__":
    solution = Solution()

    # Example 1
    example1: list[int] = [10, 5, 1, 7, 40, 50]
    print(solution.countElementsLessThanRoot(example1))  # Output: 3

    # Example 2
    example2: list[int] = [25, 15, 10, 20, 30, 35, 40]
    print(solution.countElementsLessThanRoot(example2))  # Output: 3

    # Example 3
    example3: list[int] = [40, 30, 20, 35, 50, 60]
    print(solution.countElementsLessThanRoot(example3))  # Output: 4

Complexity

  • ⏰ Time complexity: O(log n) due to binary search approach
  • 🧺 Space complexity: O(1)