Find the longest sub array of consecutive numbers with a while loop

Viewed 734

I want to write a function with a while-statement that determines the length of the largest consecutive subarray in an array of positive integers. (There is at least one consecutive array.) For instance:

Input: [6, 7, 8, 6, 12, 1, 2, 3, 4] --> [1,2,3,4]
Output: 4

Input: [5, 6, 1, 8, 9, 7]  --> [1,8,9]
Output: 3

Normally I would try to use for-loops and the array.push method later on, however, to get more practice I wanted to use a while-loop and another 'array-lengthening' method, not sure how it's called, see below.

My try:

function longestSub (input) {

  let i=0;
  let idx=0;
  let counterArr=[1];                   //init. to 1 because input [4,5,3] equals sub-length 2

  while(i<input.length) {

    if (input[i]+1 > input[i]) {
      counterArr[0+idx] += 1  
    }
    else {
      i=input.indexOf(input[i]);                     //should start loop at this i-value again
      idx +=1;
      counterArr[0+idx] = 1;                         //should init new array index
    }
    i++
  }
return Math.max(...counterArr)
  }

My idea was that the else-statement would reset the if-statement when it fails and start again from the position it failed at with updated variables. It would also initialize another array index with value 1 that gets subsequently updated afterwards with the if-statement.

Finally I have a counterArr like [1,2,3] where 3 stands for the largest consecutive subarray. Thanks everyone reading this or helping a beginner like me to get a deeper understanding of Javascript.

3 Answers

Here is a simple solution using while loop:

let arr =[6, 7, 8, 6, 12, 1, 2, 3, 4]
let endIndx = 0, maxLength = 0, indx = 1,tempMax = 0;
while (indx < arr.length) {
  if (arr[indx] > arr[indx - 1])
    tempMax++;
  else {
    if (maxLength <= tempMax) {
      maxLength = tempMax+1
      endIndx = indx
      tempMax=0;
    }
  }
  ++indx
}
if (maxLength < tempMax) {
      maxLength = tempMax
      endIndx = indx
    }
console.log("Sub array of consecutive numbers: ", arr.slice(endIndx-maxLength,endIndx))
console.log("Output :",maxLength)

You could take an approach which just counts the length and checks with the max found length if the continuous items.

function longestSub(input) {
    let i = 1,          // omit first element and use later element before this index
        max = 0,
        tempLength = 1; // initialize with one
    
    if (!input.length) return 0;

    while (i < input.length) {
        if (input[i - 1] < input[i]) {
            tempLength++;
        } else {
            if (max < tempLength) max = tempLength;
            tempLength = 1;
        }
        i++;
    }
    if (max < tempLength) max = tempLength;
    return max;
}

console.log(longestSub([]));                              // 0
console.log(longestSub([6, 7, 8, 6, 12]));                // 3
console.log(longestSub([5, 6, 1, 2, 8, 9, 7]));           // 4
console.log(longestSub([6, 7, 8, 6, 12, 1, 2, 3, 4, 5])); // 5

Unless this really is a learning exercise, I'd rather focus on the approach than on the implementation.

Create a function that slices an array of numbers into arrays of consecutive numbers:

The first two conditions deal with the simplest cases:

  • If input is empty, output is empty [] -> []
  • If input is exactly one element, the output is known already [42] -> [[42]]

Then comes the "meat" of it. The output is an array of array. Let's start by creating the first sub array with the first element of the initial array. Let's use [6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5] as the input.

Start with [[6]] then iterate over [7, 8, 6, 12, 1 ,2 ,3, 4, 5]. Here are the result at each iteration:

  1. 7 > 6 true -> [[6,7]]
  2. 8 > 7 true -> [[6,7,8]]
  3. 6 > 8 false -> [[6],[6,7,8]]
  4. 12 > 6 true -> [[6,12],[6,7,8]]
  5. 1 > 12 false -> [[1],[6,12],[6,7,8]]
  6. 2 > 1 true -> [[1,2],[6,12],[6,7,8]]
  7. 3 > 2 true -> [[1,2,3],[6,12],[6,7,8]]
  8. 4 > 3 true -> [[1,2,3,4],[6,12],[6,7,8]]
  9. 5 > 4 true -> [[1,2,3,4,5],[6,12],[6,7,8]]
const slices =
  xs =>
      xs.length === 0 ? []
    : xs.length === 1 ? [[xs[0]]]
                      : xs.slice(1).reduce
                          ( ([h, ...t], x) =>
                              x >= h[h.length - 1]
                                ? [h.concat(x), ...t]
                                : [[x], h, ...t]
                          , [[xs[0]]]
                          );

slices([6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5]);

//=> [ [1, 2, 3, 4, 5]
//=> , [6, 12]
//=> , [6, 7, 8]
//=> ]

Then you create a function that takes an array of slices and return the biggest one:

const max_slices =
  xs =>
    xs.reduce
      ( (a, b) =>
          a.length > b.length
            ? a
            : b
      );

max_slices(slices([6, 7, 8, 6, 12, 1 ,2 ,3, 4, 5]));

//=> [1, 2, 3, 4, 5]
Related