优化的javascript代码,在数组中找到3个最大的元素及其索引?

til*_*lak 8 javascript sorting algorithm

我需要更优化的javascript代码才能找到数组中最大的3个元素.我试过这个代码.

var maxIndex = new Array();
var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

function findLargest3(){ 

      maxPoints[0]=0;
      maxPoints[1]=0;
      maxPoints[2]=0;
    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[0]){                               
             maxPoints[0] = scoreByPattern[i];
             maxIndex[0]=i;   
        }


    }

    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[1] && scoreByPattern[i]< maxPoints[0] ){                               
             maxPoints[1] = scoreByPattern[i];
             maxIndex[1]=i;   
        }            
    }

    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[2] && scoreByPattern[i]< maxPoints[1] ){                               
             maxPoints[2] = scoreByPattern[i];
             maxIndex[2]=i;   
        }            
    }

alert(scoreByPattern+"/******/"+maxPoints[0]+"/"+maxPoints[1]+"/"+maxPoints[2]);
//alert(maxIndex);
}
Run Code Online (Sandbox Code Playgroud)

如何优化以上?(我需要最大数字的索引)是否有其他简单的方法来解决问题?

huy*_*itw 11

修改版

我修改了我的答案,使其更通用.它搜索数组中n个最大元素的索引:

var scoreByPattern = [93,255,17,56,91,98,33,9,38,55,78,29,81,60];

function findIndicesOfMax(inp, count) {
    var outp = [];
    for (var i = 0; i < inp.length; i++) {
        outp.push(i); // add index to output array
        if (outp.length > count) {
            outp.sort(function(a, b) { return inp[b] - inp[a]; }); // descending sort the output array
            outp.pop(); // remove the last index (index of smallest element in output array)
        }
    }
    return outp;
}

// show original array
console.log(scoreByPattern);

// get indices of 3 greatest elements
var indices = findIndicesOfMax(scoreByPattern, 3);
console.log(indices);

// show 3 greatest scores
for (var i = 0; i < indices.length; i++)
    console.log(scoreByPattern[indices[i]]);
Run Code Online (Sandbox Code Playgroud)

这是一个jsFiddle

  • 好答案; 简洁且输出与OP相匹配。但是,我不认为有理由为每个循环调用“sort”。循环是“O(N)”,但排序是“O(N Log(N))”。我认为排序一次并切片“计数”通常会提高性能。即 `for (var i = 0; i &lt; inp.length; i++) { outp.push(i); } outp.sort(function(a, b) { return inp[b] - inp[a]; }); return outp.slice(0, count);` 在我的机器 Win10 Firefox 上,我测量到大约 20% 的改进和相同的输出。 (2认同)

Ror*_*san 6

对数组进行降序排序,然后得到它的前三个元素:

var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

findLargest3();

function findLargest3(){
    // sort descending
    scoreByPattern.sort(function(a,b) {
        if (a < b) { return 1; }
        else if (a == b) { return 0; }
        else { return -1; }
    });

    alert(scoreByPattern+"/******/"+scoreByPattern[0]+"/"+scoreByPattern[1]+"/"+scoreByPattern[2]);
}
Run Code Online (Sandbox Code Playgroud)

示例小提琴

  • 我认为排序很糟糕,你可以在O(n)中完成. (4认同)
  • 我想,如果您使用排序函数进行排序,它会比执行正常的内置“sort()”后跟“reverse()”要慢。如果您指定排序函数,您也可以执行“forEach”并只取出最高的 3 个值。 (2认同)
  • 我觉得这并没有真正回答问题;我不知道为什么它得到如此高的支持。这将返回索引“[0,1,2]”,而不是OP提供的解决方案中的“[4,0,3]”。这也具有对原始数组进行“排序”的副作用,而OP发布的解决方案却没有。为了使这个解决方案发挥作用,您必须复制原始数组,对副本进行排序以获取前 3 个值,并在原始数组上使用“indexOf”之类的内容来获取索引。到那时,我认为性能可能会比原来的解决方案更差。 (2认同)

Chr*_*oph 6

没有排序巨大的数组:O(n)考虑大数组运行.返回一个数组数组,[x,y]其中xvalue y是大数组中的值和索引.

var ar = [3,172,56,91,98,33,9,38,55,78,291,81,60];
console.log(`input is: ${ar}`);

function getMax(ar){
    if (ar.length < 3) return ar;
    var max = [[ar[0],0],[ar[1],1],[ar[2],2]],
        i,j;
    
    for (i = 3;i<ar.length;i++){
        for (j = 0;j<max.length;j++){
            if (ar[i] > max[j][0]){
                max[j] = [ar[i],i];
                if (j<2){
                    max.sort(function(a,b) { return a[0]-b[0]; });
                }
               break;            
            }
        }
    }
    return max;
}
result = getMax(ar);

console.log('output [number,index] is:');
console.log(result);
Run Code Online (Sandbox Code Playgroud)