{x}
blog image

Count Elements With Strictly Smaller and Greater Elements

Given an integer array nums, return the number of elements that have both a strictly smaller and a strictly greater element appear in nums.

 

Example 1:

Input: nums = [11,7,2,15]
Output: 2
Explanation: The element 7 has the element 2 strictly smaller than it and the element 11 strictly greater than it.
Element 11 has element 7 strictly smaller than it and element 15 strictly greater than it.
In total there are 2 elements having both a strictly smaller and a strictly greater element appear in nums.

Example 2:

Input: nums = [-3,3,3,90]
Output: 2
Explanation: The element 3 has the element -3 strictly smaller than it and the element 90 strictly greater than it.
Since there are two elements with the value 3, in total there are 2 elements having both a strictly smaller and a strictly greater element appear in nums.

 

Constraints:

  • 1 <= nums.length <= 100
  • -105 <= nums[i] <= 105

Solution Explanation: Counting Elements with Strictly Smaller and Greater Elements

This problem asks us to find the number of elements in an array that have both a strictly smaller and a strictly greater element within the same array. The most efficient approach involves finding the minimum and maximum values in the array and then iterating through the array to count elements that fall strictly between these two extremes.

Approach:

  1. Find Minimum and Maximum: The first step is to efficiently determine the minimum (mi) and maximum (mx) values present in the input array nums. This can be done using built-in functions like min() and max() in Python or Arrays.stream().min().getAsInt() and Arrays.stream().max().getAsInt() in Java.

  2. Count Intermediate Elements: After finding mi and mx, we iterate through the array nums. For each element x, we check if it satisfies the condition mi < x < mx. If it does, we increment a counter (ans). This condition ensures that the element is strictly greater than the minimum and strictly smaller than the maximum.

  3. Return the Count: Finally, we return the value of the counter ans, which represents the number of elements satisfying the given condition.

Time and Space Complexity Analysis:

  • Time Complexity: The algorithm consists of three main steps: finding the minimum and maximum (which takes O(n) time in a naive approach, or O(n log n) if using a sorting-based approach, though O(n) is achievable with a single pass), iterating through the array once (O(n)), and returning the result (O(1)). Therefore, the overall time complexity is dominated by the linear iterations, making it O(n).

  • Space Complexity: The algorithm uses a constant amount of extra space to store variables like mi, mx, and ans. Hence, the space complexity is O(1). This is because the space used does not scale with the input size.

Code Implementation in Different Languages:

The following code snippets demonstrate the solution in several popular programming languages:

Python:

class Solution:
    def countElements(self, nums: List[int]) -> int:
        mi, mx = min(nums), max(nums) #O(n) time for min and max
        return sum(mi < x < mx for x in nums) #O(n) time for iteration

Java:

import java.util.Arrays;
 
class Solution {
    public int countElements(int[] nums) {
        int mi = Arrays.stream(nums).min().getAsInt(); //O(n)
        int mx = Arrays.stream(nums).max().getAsInt(); //O(n)
        int ans = 0;
        for (int x : nums) { //O(n)
            if (mi < x && x < mx) {
                ans++;
            }
        }
        return ans;
    }
}

C++:

#include <algorithm>
#include <vector>
#include <numeric> //for accumulate
 
class Solution {
public:
    int countElements(std::vector<int>& nums) {
        auto [mi, mx] = std::minmax_element(nums.begin(), nums.end()); //O(n)
        return std::count_if(nums.begin(), nums.end(), [&](int x){ return *mi < x && x < *mx; }); //O(n)
    }
};

Go:

import (
	"math"
	"sort"
)
 
func countElements(nums []int) int {
	mi, mx := math.MaxInt32, math.MinInt32 //Initialize to extreme values
	for _, x := range nums {
		if x < mi {
			mi = x
		}
		if x > mx {
			mx = x
		}
	}
 
	count := 0
	for _, x := range nums {
		if x > mi && x < mx {
			count++
		}
	}
	return count
}

TypeScript:

function countElements(nums: number[]): number {
    const mi = Math.min(...nums); //O(n)
    const mx = Math.max(...nums); //O(n)
    let count = 0;
    for (const num of nums) { //O(n)
        if (num > mi && num < mx) {
            count++;
        }
    }
    return count;
}

These code examples all follow the same basic approach, differing only in syntax and specific library functions used for finding minimum and maximum values and iterating through the array. They all achieve the optimal O(n) time and O(1) space complexity.