繁体   English   中英

查找数组中相同数字的最长出现次数

[英]Find longest occurrence of same number in array

使用 JavaScript,我试图找到一种方法来查找数组中相同数字(在本例中为 1)的最长出现次数。

例如,这是一个示例数组: [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]

我想编写一个返回“5”的函数,因为数字 1 连续出现 5 次。 (它也连续出现 3 次和 2 次,但我是在最长的一次出现之后)。

到目前为止,我已经写了:

function streak(arr) {
    var i,
        temp,
        streak,
        length = arr.length;

    for(i=0; i<length; i++) {
        if (arr[i] === 1) {
            streak += 1;
        } else {
            temp = streak;
            break;
        }
    }
}

我知道我需要一些方法来知道如果我发现了一个事件我从哪里停止,但我感觉有点卡住了。

任何指针?

我稍微修改了你的函数。 您需要将最高连续记录存储为与当前连续记录不同的变量,并在循环中必要时覆盖该变量 - 最后在函数结束时返回该变量。

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

如果您还想跟踪最高连续记录的是多少,请在函数的开头定义另一个变量,在保存最高连续记录时保存它的值,并将其作为数组返回:

    // 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"]

演示同时返回

另一种方法。 我正在将数组转换为字符串。 正则表达式具有反向引用,可确保仅匹配相同字符的序列。 此外,当execg标志一起使用时,重复执行将从最后一个匹配的末尾开始,而不是从头开始。

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);

您的问题:

  • 你不存储当前的连胜纪录
  • 您没有指定何时streak大于旧连胜

用这个:

function streak(arr) {
    var i,
        temp,
        streak = 1,
        maxStreak = 0,
        prevNumber,
        length = arr.length;

    for(i=1; i<length; i++) {
        prevNumber = arr[i-1];
        if (arr[i] == prevNumber) {
            streak += 1;
        } else {
            if(streak > maxStreak) {
                maxStreak = streak;
                streak = 1;
            }
        }
    }
    return maxStreak;
}

演示

您将需要另外两个数组。

  1. 使用循环存储源数组中的不同数字
  2. 制作第二组数组,它​​等于具有不同数字的第一组数组的长度。
  3. 使循环等于第一组数组的长度,然后根据其索引将值推送到第二组数组。
  4. 使用第二组数组再次进行循环,然后您将使用第二组数组的索引找到最多出现的次数
  5. 最后,使用从步骤 4 中获得的索引从第一组数组中获取数字。

我没有制作代码让你先自己尝试,因为你只是要求一些指针

替代方法:使用正则表达式并将数组转换为字符串。

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('').match(/1+/g);
console.log(process ? process.sort().pop() : "No ocurrences");

您可以使用Array#reduce并返回实际相同项目序列的起始索引。 如果项目不相等,则检查并更新计数器。

 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], maxCount = 0, maxValues; array.reduce(function (j, a, i, aa) { if (aa[j] === a) { return j; } if (i - j === maxCount){ maxValues.push(aa[j]); } if (i - j > maxCount) { maxCount = i - j; maxValues = [aa[j]]; } return i; }, -1); console.log(maxCount); console.log(maxValues);

这是一种方法:

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

我的建议:

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/

您可以通过查看给定索引中的所有匹配项并跳转到下一个不匹配项的索引来使用更少的迭代。

当剩余的项目少于您找到的最大值时,您也可以退出。

function maxRepeats(arr){
    var L= arr.length, i= 0, 
    max= 1, count= 0;
    while(L-i > max){
        while(arr[i+count]=== arr[i])++count;
        if(count > max) max= count;
        i+= count;
        count= 0;
    }
    return max;
}
var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 
1, 1, 1, 1, 4, 7, 2, 3, 1, 1, 4, 3];

最大重复次数(A); 返回 5

找到重复最大次数的多个项目并不容易,因为您必须先找到最大数量才能列出它们。 如果您真的只需要最大数量,请忽略:

function mostRepeats(arr, maximum){
    var i= 0, max= maximum || 1, 
    L= arr.length-max, 
    count= 0, index= [];
    while(i<L){
        while(arr[i+count]=== arr[i])++count;
        if(count=== maximum) index.push(arr[i]+' starting at #'+i);
        else if(count > max) max= count;
        i+= count;
        count= 0;
    }
    if(max===1) return 'No repeats';
    return maximum? max+' repeats of: '+index.join(', '): mostRepeats(arr, max);
}

var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 1, 1, 
1, 1, 4, 7, 2, 3, 3, 3, 3, 3, 1, 1, 4, 3];

mostRepeats(A);返回:

5 次重复:1 从 #11 开始,3 从 #19 开始

不幸的是,由于缺乏声誉,我还不能发表评论,所以我会将此作为答案发布。 对于我的任务Robbie Averill的解决方案是完美的,但它包含一个小错误。 我有一个由 2 个值组成的数组 - 0 和 1.5,但上面提到的代码只计算“1.5”值,尽管我有“0”在更高的连续重复。 问题是 value 没有在这里进行严格的比较:

if(temp != '' && temp == arr[i]) {

解决方法很简单: if(temp !== '' && temp == arr[i]) {

我已经用这个修复更新了 Robbie 的 jsfiddler: http : //jsfiddle.net/d5X2k/5/

不幸的是,一个问题被标记为重复,但它与这个不同。 所以我必须把我的答案放在这里,对不起……

 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));

正如您所看到的,这是一个比 reduce 更慢的更好的解决方案:

 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));

输入数组:

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,
];

最短的解决方案:

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

使用正则表达式替代(剧透:它比使用 reduce() 的解决方案慢约 25%。请参阅下面的“使用 reduce() 的现代方法” ):

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

直截了当,老派风格,人类可读和最快的解决方案:

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;
}

使用 reduce() 的现代方法(只是比上面的老式代码慢一点):

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;

性能测试,Reduce() 与老式 for(): https : //jsbench.me/ifkgsin56z/1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM