Find longest occurrence of same number in array

前端 未结 12 1438
一生所求
一生所求 2021-01-05 17:49

Using JavaScript, I\'m trying to find a way to find the longest occurrence of the same number (in this case, 1) in an array.

For instance, here\'s a sample array:

相关标签:
12条回答
  • 2021-01-05 17:52

    I've modified your function slightly. You need to store the highest streak as a separate variable from the current streak, and overwrite that where necessary in your loop - finally returning that variable at the end of your function.

    function streak(arr) {
        var i,
            temp,
            streak,
            length = arr.length,
            highestStreak = 0;
    
        for(i = 0; i < length; i++) {
            // check the value of the current entry against the last
            if(temp != '' && temp == arr[i]) {
                // it's a match
                streak++;
            } else {
                // it's not a match, start streak from 1
                streak = 1;
            }
    
            // set current letter for next time
            temp = arr[i];
    
            // set the master streak var
            if(streak > highestStreak) {
                highestStreak = streak;
            }
        }
    
        return highestStreak;
    }
    
    var array = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
    
    console.log(streak(array)); // 5
    

    And if you want to also track what the value of the highest streak was, define another variable at the start of your function, save the value of it when you save the highest streak, and return it as an array:

        // set the master streak var
        if(streak > highestStreak) {
            highestStreakValue = temp;
            highestStreak = streak;
        }
    }
    
    return [highestStreak, highestStreakValue];
    
    
    var array = [2,5,3,1,1,1,3,7,9,6,4,'a','a','a','a','a',4,7,2,3,1,1,4,3];
    console.log(streak(array)); // [5, "a"]
    

    Demo returning both

    0 讨论(0)
  • 2021-01-05 17:54

    My proposal:

    function getLongestRow(inputArray) {
        // Initialize dummy variables
        var start = inputArray[0], curRowLen = 0, maxRowLen = 0, maxRowEle = 0;
    
        // Run through the array
        for(var i = 0;i < inputArray.length;i++) {
            // If current Element does not belong to current row
            if(inputArray[i] != start) {
                // If current row is longer than previous rows, save as new longest row
                if(curRowLen > maxRowLen) {
                    maxRowLen = curRowLen;
                    maxRowEle = start;
                    curRowLen = 1;
                }
                // Start new row
                start = inputArray[i];
            } else {
                // Current element does belongt to current row, increase length
                curRowLen++;
            }
        }
    
        // Check whether last row was longer than previous rows
        if(curRowLen > maxRowLen) {
            maxRowLen = curRowLen;
            maxRowEle = start;
        }
    
        // Return longest row & element longest row consits of
        console.log('The longest row in your array consists of '+maxRowLen+' elements of '+maxRowEle+'.');
    }
    

    JsFiddle: http://jsfiddle.net/hdwp5/

    0 讨论(0)
  • 2021-01-05 17:56

    Here's a way to do it:

    var values = function(obj) {
      var res = [];
      for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
          res.push(obj[i]);
        }
      }
      return res;
    };
    
    var countStreak = function(xs) {
      var res = xs.reduce(function(acc, x, i) {
        if (x === xs[i+1]) {
          acc[x] = acc[x]+1 || 2;
        } else {
          acc[x] = acc[x]-1 || 0;
        }
        return acc;
      },{})
      return Math.max.apply(0, values(res));
    };
    
    var ns = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]
    countStreak(ns) //=> 5
    
    0 讨论(0)
  • 2021-01-05 17:57

    An alternative approach. I'm converting the array to a string. The regular expression has a backrefence, which ensures that only sequences of the same character are matched. Also when exec is used with the g flag, repeated executions will continue from the end of last match, and not from the beginning.

    var arr = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
    var str = arr.join('');
    var regex = /(.)\1*/g;
    var match;
    var largest = '';
    
    while (match = regex.exec(str)) {
      largest = match[0].length > largest.length ? match[0] : largest;
    }
    
    console.log(largest.length);
    
    0 讨论(0)
  • 2021-01-05 17:59

    Unfortunatly, a question has been marked as duplicate, but it was not the same as this one. So I must put my answer here, sorry…

    let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1]
      , arr = []
      , n = 0
      , res = null ;
    
    for(let i of tab)
    {
        if ( i ) { ++ n }
        else if ( n ) { arr.push(n) ; n = 0 }
    }
    arr.push(n) ;
    
    res = Math.max(...arr);
    
    console.log("Streak with 1 is ", Math.max(...arr));

    It's a better solution than with reduce, slower, as you can see:

    let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1];
    let arr = [];
    let n = 0;
    let res = null;
    
    let loop = 0;
    let start = new Date().getTime();
    
    while (loop < 1000000){
      ++ loop;
      
      arr = [];
      for(let i of tab)
      {
          if ( i ) { ++ n }
          else if ( n ) { arr.push(n) ; n = 0 }
      }
      arr.push(n);
      res = Math.max(...arr);
    }
    let end = new Date().getTime();
    console.log("laps old fashion = ", end - start);
    
    loop = 0;
    let streaks = null;
    start = new Date().getTime();
    while (loop < 1000000){
      ++ loop;
      streaks = tab.reduce((res, n) => 
        (n ? res[res.length-1]++ : res.push(0), res)
      , [0]);
      res = Math.max(...streaks);
    }
    end = new Date().getTime();
    console.log("laps reduce = ", end - start);
    
    console.log("Streak with 1 is ", Math.max(...arr));

    0 讨论(0)
  • 2021-01-05 18:04

    Input array:

    const seq = [
    0, 0, 0,
    1, 1, 1,
    1, 1, 1, 1, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1,
    0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1,
    ];
    

    Shortest solutions:

    console.log(Math.max(...Array.from(seq.join("").matchAll(/(.)\1+/g), m=>m[0].length)))
    

    Alternative with regexp (spoiler: it's ~25%, slower than solution with reduce(). See "Modern approach with reduce()" below):

    const longestSeq = (seq) => {
        let max = 0;
        seq.join("").replace(/(.)\1+/g, m=> max = Math.max(max, m.length));
        return max;
    };
    

    Straightforward, old-school style, human readable and fastest solution:

    let longestSeq = () => {
        let maxCount = 0,
            curCount = 0,
            curItem, prevItem,
            l = seq.length+2, // +1+1 to finish last sequence and compare 'undefined' with previous
            i = 0;
        for (; i < l; ++i) {
          curItem = seq[i];
          if (curItem === prevItem) ++curCount;
          else {
            if (curCount > maxCount) maxCount = curCount;
            curCount = 1;
            prevItem = curItem;
          }
        }
        return maxCount;
    }
    

    Modern approach with reduce() (just very little slower than old-school code above):

    const longestSeq = (seq) => seq
        .reduce(
            ({count, max}, item) => item === 0
            ? { count: ++count, max: Math.max(count, max) }
            : { count: 0, max: max },
          { count: 0, max: 0} )
        .max;
    

    Performance test, Reduce() vs old-school for(): https://jsbench.me/ifkgsin56z/1

    0 讨论(0)
提交回复
热议问题