1491. Average Salary Excluding the Minimum and Maximum Salary
Problem Description
You are given an array of unique integers representing employee salaries. Each element salary[i]
represents the salary of the i-th employee.
Your task is to calculate the average salary of all employees after excluding both the minimum and maximum salaries from the calculation.
For example, if you have salaries [4000, 3000, 1000, 2000]
, you would:
- Identify the minimum salary:
1000
- Identify the maximum salary:
4000
- Calculate the average of the remaining salaries:
(3000 + 2000) / 2 = 2500
The solution computes this by:
- Finding the sum of all salaries using
sum(salary)
- Subtracting the minimum salary using
min(salary)
- Subtracting the maximum salary using
max(salary)
- Dividing the result by
len(salary) - 2
(since we removed 2 salaries)
The formula used is: (total_sum - min_salary - max_salary) / (n - 2)
where n
is the total number of employees.
Note that answers within 10^-5
of the actual answer will be accepted, meaning small floating-point differences are acceptable.
Intuition
When we need to find an average while excluding certain values, the straightforward approach would be to remove those values from our dataset and then calculate the average of what remains. However, there's a more efficient way to think about this problem.
Instead of creating a new array without the minimum and maximum values, we can work with the mathematical property of averages. The average is simply the sum divided by the count. Since we want to exclude the minimum and maximum values, we need:
- The sum without these two values
- The count without these two values
The key insight is that we can calculate the sum of the remaining elements by taking the total sum and subtracting the unwanted values. This is more efficient than filtering the array and then summing, as it requires only one pass through the array to get all three values: sum()
, min()
, and max()
.
Think of it like calculating the average score of a class after removing the highest and lowest scores. Rather than rewriting the list of scores, you can simply:
- Add up all the scores
- Find and subtract the highest score
- Find and subtract the lowest score
- Divide by the new count (original count minus 2)
This gives us the formula: average = (sum - min - max) / (n - 2)
This approach is elegant because it accomplishes the task in O(n)
time with only a single conceptual pass through the data (even though sum()
, min()
, and max()
each traverse the array, they're all linear operations), and it uses O(1)
extra space since we're not creating any new data structures.
Learn more about Sorting patterns.
Solution Approach
The solution follows a direct simulation approach as described in the reference. We implement the mathematical formula derived from our intuition to calculate the average after excluding extremes.
Implementation Steps:
-
Calculate the total sum: Use Python's built-in
sum()
function to get the sum of all salaries in the array. -
Find and subtract the minimum: Use
min()
to find the smallest salary and subtract it from the total sum. -
Find and subtract the maximum: Use
max()
to find the largest salary and subtract it from the remaining sum. -
Calculate the average: Divide the adjusted sum by
len(salary) - 2
since we've removed two elements (the minimum and maximum).
The implementation in a single line:
s = sum(salary) - min(salary) - max(salary)
return s / (len(salary) - 2)
Why this works:
- Since all salaries are unique (as stated in the problem), we don't need to worry about edge cases where multiple employees have the same minimum or maximum salary.
- The mathematical operation
(sum - min - max) / (n - 2)
gives us exactly what we need: the average of all elements except the extremes.
Time and Space Complexity:
- Time:
O(n)
where n is the number of employees, as we need to traverse the array to find sum, min, and max - Space:
O(1)
as we only use a constant amount of extra space to store the intermediate sum
This simulation approach is optimal for this problem because it's both intuitive and efficient, avoiding unnecessary array manipulations while directly computing the desired result.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with the salary array [8000, 9000, 2000, 3000, 6000, 1000]
.
Step 1: Calculate the total sum
sum(salary) = 8000 + 9000 + 2000 + 3000 + 6000 + 1000 = 29000
Step 2: Find the minimum salary
- Looking through the array: 8000, 9000, 2000, 3000, 6000, 1000
min(salary) = 1000
Step 3: Find the maximum salary
- Looking through the same array: 8000, 9000, 2000, 3000, 6000, 1000
max(salary) = 9000
Step 4: Apply the formula
- Adjusted sum =
29000 - 1000 - 9000 = 19000
- Number of remaining employees =
6 - 2 = 4
- Average =
19000 / 4 = 4750.0
Verification:
If we manually exclude 1000 and 9000, we're left with [8000, 2000, 3000, 6000]
.
The average of these four values is (8000 + 2000 + 3000 + 6000) / 4 = 19000 / 4 = 4750.0
β
This confirms our formula works correctly. By using (sum - min - max) / (n - 2)
, we efficiently computed the average salary excluding the extremes without creating a new filtered array.
Solution Implementation
1class Solution:
2 def average(self, salary: List[int]) -> float:
3 """
4 Calculate the average salary excluding the minimum and maximum salaries.
5
6 Args:
7 salary: List of integers representing salaries
8
9 Returns:
10 Float representing the average of salaries excluding min and max
11 """
12 # Calculate the total sum and subtract both the minimum and maximum values
13 total_sum = sum(salary) - min(salary) - max(salary)
14
15 # Divide by the count of remaining elements (total count minus 2)
16 average_salary = total_sum / (len(salary) - 2)
17
18 return average_salary
19
1class Solution {
2 public double average(int[] salary) {
3 // Initialize variables
4 int totalSum = 0;
5 int minSalary = Integer.MAX_VALUE; // Start with maximum possible value
6 int maxSalary = Integer.MIN_VALUE; // Start with minimum possible value
7
8 // Iterate through all salaries to find sum, minimum, and maximum
9 for (int currentSalary : salary) {
10 minSalary = Math.min(minSalary, currentSalary);
11 maxSalary = Math.max(maxSalary, currentSalary);
12 totalSum += currentSalary;
13 }
14
15 // Remove minimum and maximum salaries from total sum
16 totalSum -= (minSalary + maxSalary);
17
18 // Calculate average excluding minimum and maximum
19 // Convert to double for decimal division
20 return totalSum * 1.0 / (salary.length - 2);
21 }
22}
23
1class Solution {
2public:
3 double average(vector<int>& salary) {
4 // Initialize variables to track sum and extremes
5 int totalSum = 0;
6 int minSalary = 1e7; // Initialize to a large value
7 int maxSalary = 0; // Initialize to smallest possible value
8
9 // Iterate through all salaries to calculate sum and find min/max
10 for (int currentSalary : salary) {
11 totalSum += currentSalary;
12 minSalary = min(minSalary, currentSalary);
13 maxSalary = max(maxSalary, currentSalary);
14 }
15
16 // Remove the minimum and maximum salaries from the total
17 totalSum -= (minSalary + maxSalary);
18
19 // Calculate and return the average, excluding min and max
20 // Cast to double for decimal precision
21 return static_cast<double>(totalSum) / (salary.size() - 2);
22 }
23};
24
1/**
2 * Calculates the average salary excluding the minimum and maximum values
3 * @param salary - Array of salary values
4 * @returns The average of salaries excluding min and max values
5 */
6function average(salary: number[]): number {
7 // Initialize maximum value to negative infinity for comparison
8 let maxSalary: number = -Infinity;
9
10 // Initialize minimum value to positive infinity for comparison
11 let minSalary: number = Infinity;
12
13 // Initialize sum accumulator
14 let totalSum: number = 0;
15
16 // Iterate through all salary values
17 for (const currentSalary of salary) {
18 // Add current salary to total sum
19 totalSum += currentSalary;
20
21 // Update maximum salary if current is larger
22 maxSalary = Math.max(maxSalary, currentSalary);
23
24 // Update minimum salary if current is smaller
25 minSalary = Math.min(minSalary, currentSalary);
26 }
27
28 // Calculate average by removing min and max from sum
29 // then dividing by count minus 2 (excluded values)
30 return (totalSum - maxSalary - minSalary) / (salary.length - 2);
31}
32
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array salary
. This is because:
sum(salary)
iterates through alln
elements once:O(n)
min(salary)
iterates through alln
elements once:O(n)
max(salary)
iterates through alln
elements once:O(n)
- The subtraction and division operations are constant time:
O(1)
- Total:
O(n) + O(n) + O(n) + O(1) = O(n)
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space to store:
- The variable
s
for the sum - The temporary values for
min(salary)
andmax(salary)
- These variables do not scale with the input size
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Multiple Traversals Inefficiency
The current solution makes three separate passes through the array (sum()
, min()
, and max()
), which while still O(n), performs unnecessary repeated iterations.
Better Approach: Calculate all three values in a single pass:
def average(self, salary: List[int]) -> float:
total_sum = 0
min_sal = float('inf')
max_sal = float('-inf')
for sal in salary:
total_sum += sal
min_sal = min(min_sal, sal)
max_sal = max(max_sal, sal)
return (total_sum - min_sal - max_sal) / (len(salary) - 2)
2. Integer Division Error (Language-Specific)
In languages like Python 2 or C++, using integer division could truncate the result:
# Wrong in Python 2 or similar languages
result = (total_sum - min_sal - max_sal) / (len(salary) - 2) # May truncate
# Correct approach for integer division languages
result = float(total_sum - min_sal - max_sal) / (len(salary) - 2)
3. Edge Case: Small Arrays
While the problem likely guarantees at least 3 elements, not validating this could cause division by zero:
def average(self, salary: List[int]) -> float:
if len(salary) < 3:
# Handle edge case appropriately
return 0.0 # or raise an exception
total_sum = sum(salary) - min(salary) - max(salary)
return total_sum / (len(salary) - 2)
4. Floating Point Precision Issues
For very large salary values, floating-point arithmetic might introduce precision errors. While the problem accepts answers within 10^-5, be aware of potential precision loss:
# For extreme precision requirements, consider using Decimal
from decimal import Decimal
def average(self, salary: List[int]) -> float:
salary_decimals = [Decimal(s) for s in salary]
total = sum(salary_decimals) - min(salary_decimals) - max(salary_decimals)
return float(total / (len(salary) - 2))
5. Assuming Unique Values
While the problem states salaries are unique, if this constraint were removed, the logic would still work correctly. However, developers might incorrectly try to handle duplicate min/max values specially, which isn't necessary:
# Unnecessary complication (DON'T DO THIS):
if salary.count(min(salary)) > 1: # This is unnecessary
# Special handling...
# The original approach works fine even with duplicates
Which data structure is used in a depth first search?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!