Working with minimum and maximum values

Finding the smallest or greatest value of an array of numbers seems to be easy and it more or less is. In this post I will show some simple solutions for finding the greatest value and the lowest absolute difference in an array.

Finding the greater of two numbers

JavaScript’s Math object provides some good methods for simple calculations and comparisons.

For example, finding the greater of two numbers is easy:

console.log(Math.max(23, 19)); // 23

We can use the max method available on the Math object. It accepts numbers as arguments and returns the highest of these numbers.

If a value cannot be converted to a number, it returns NaN, which is a falsy value:

console.log(Math.max(41, 'dog')); // NaN

What if we have an array of numbers and need to find the greatest of these numbers? We don’t necessarily know how many elements the array has!

Getting the greatest value in an array

Arrays cannot be passed as an argument to Math.max, hence we need to apply a trick here.

Before ES6, we could use apply to call Math.max with a list of arguments:

const numbers = [5, 23, -2, -19, 11];

console.log(Math.max.apply(null, numbers)); // 23

apply calls the function (in our case Math.max) with a pre-defined this value (in our case null because we don’t need any special context other than global) as the first argument and an array (second argument, numbers in our case).

Although apply is great and can be used in many situations, ES6 provides a nice and easy solution with the spread operator, which makes individual arguments for the Math.max method from the elements of the array:

console.log(Math.max(...numbers)); // 23

I personally think that the ES6 way is easier and more elegant than apply, so I give it the thumbs up.

In case of large number (like tens of thousands) of elements in the array these solutions might not work properly as the number of arguments applied to a function can be limited by some engines.

We can solve this problem with sorting the numbers first in descending order and then accessing the first element:

const returnMax = (arr) => {
  return arr.sort((a, b) => a < b)[0];
};

console.log(returnMax(numbers)); // 23

Or, an even simpler solution is to use reduce:

const returnMax2 = (arr) => {
  return arr.reduce((a, b) => Math.max(a, b));
};

console.log(returnMax2(numbers)); // 23

The methods work similarly for Math.min as well.

Minimum absolute difference

An interesting problem is to find the minimum absolute difference of any two numbers in the numbers array.

We can solve this problem with the brute force approach using two for loops, for example, but it’s so cumbersome that I don’t even show it.

Instead of comparing each element to all other elements, calculating the difference of each pair and returning the smallest of all differences, let’s have a look at another, more efficient solution.

Sort the numbers first

What if we sorted the numbers from smallest to greatest first? We could then iterate over them and compare each number with the one on its right. This way we can get away with just one iteration instead of two and still receive the same result.

Get the result with one iteration

Here’s how:

function minimumAbsoluteDifference(arr) {
  const sorted = arr.sort((a, b) => a - b);
  let min = Number.MAX_VALUE;

  for (let i = 0; i < arr.length - 1; i++) {
    const diff = sorted[i + 1] - sorted[i];

    if (diff < min) min = diff;
  }

  return min;
}

This is what we get after sorting the elements of numbers:

console.log(sorted); // [-19, -2, 5, 11, 23]

After getting the numbers in ascending order, we define an initial value for min (refers to the minimum difference) as being the highest number available in JavaScript. We can also assign the difference between the last and the first elements (the highest and the lowest values) of numbers to min, which is also a good initial value.

There’s not much magic inside the for statement. We define the difference (diff) on each iteration by subtracting the value with the smaller index (sorted[i]) from the one with the greater index (sorted[i + 1]).

Because sorted has the numbers in ascending order, it’s guaranteed that numbers coming later in the array won’t be smaller than the previous ones, so diff will always be non-negative, which is a requirement for a difference (difference is defined as an absolute value and it can’t be negative).

If diff, which is redefined on each iteration is smaller than the current value of min, we simply store the new minimum in min.

Once the loop has finished, we return min.

Let’s call the function:

console.log(minimumAbsoluteDifference(numbers)); // 6

We got 6, which is the difference between 5 and 11. As it can be seen this is the smallest difference of any two numbers in numbers.

Conclusion

That’s it for today. Again, often times we can find a nice, short and elegant solution instead of the brute force approach.

See you next time.