Write a function to determine whether an array contains consecutive numbers for at least N numbers

Posted on

Problem

I am trying to write a function to determine whether an array contains consecutive numbers for at least N numbers. For example, the input is [1,5,3,4] and 3, it turns true because the array has 3 consecutive numbers, which is [3,4,5]

Here this function requires sorting beforehand and it is not the most eloquent solution in my opinion. Can someone take a look and suggest some improvements on this?

function hasConsecutiveNums(array, N) {
  if (array.length < N) return false;
  if (N === 0) return true;
  const sortedArray = array.slice().sort((a, b) => a - b);
  let count = 0;
  let prev = null;
  for (const num of sortedArray) {
    if (prev && num === prev + 1) {
      count++;
    } else {
      count = 1;
    }
    if (count === N) return true;
    prev = num;
  }

  return false;
}

console.log(hasConsecutiveNums([1, 4, 5, 6], 3)) // true
console.log(hasConsecutiveNums([1, 4, 5, 6], 4)) // false

Solution

One issue to consider: what if an element in the array is 0, and thus falsey? Then if (prev && will not be fulfilled:

console.log(hasConsecutiveNums([-1, 0, 1], 3)) // false... oops

Another tweak to make the code a bit more elegant would be to assign prev to the first element of the array first, and initialize count to 1, thus starting comparison on the second element rather than on the first, avoiding the need to compare against null.

With this method, you also need to return true immediately if the array’s length is only 1, like the other answer recommends, otherwise there won’t be any iterations within which return true could be reached:

If, as the comment notes, you’d want [1, 2, 2, 3] to return true, de-duplicate the numbers with a Set:

function hasConsecutiveNums(array, N) {
  if (array.length < N) return false;
  if (N <= 1) return true;
  const sortedArray = [...new Set(array.slice().sort((a, b) => a - b))];
  let prev = sortedArray.shift();
  let count = 1; // first element of the array is already in prev
  for (const num of sortedArray) {
    if (num === prev + 1) {
      count++;
    } else {
      count = 1;
    }
    if (count === N) return true;
    prev = num;
  }

  return false;
}

console.log(hasConsecutiveNums([1, 4, 5, 6], 3)) // true
console.log(hasConsecutiveNums([1, 4, 5, 6], 4)) // false
console.log(hasConsecutiveNums([-1, 0, 1], 3)) // true
console.log(hasConsecutiveNums([1, 2, 2, 3], 3)) // true

Some quick remarks:

if (N === 0) return true;

can be replaced by

if (N <= 1) return true;

because in a non-empty array each element is a single “consecutive number.” This saves the sorting of the array in the case N=1N=1.

Then it suffices to check the count again only if it has been incremented.

The comparison with the previous number (or null) can be simplified slightly.

  for (const num of sortedArray) {
    if (prev === num - 1) {
      count++;
      if (count === N) return true;
    } else {
      count = 1;
    }
    prev = num;
  }

Leave a Reply

Your email address will not be published. Required fields are marked *