Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:对长度为N的数组进行排序并获得顶部m的最佳方法_Javascript_Arrays_Algorithm - Fatal编程技术网

Javascript:对长度为N的数组进行排序并获得顶部m的最佳方法

Javascript:对长度为N的数组进行排序并获得顶部m的最佳方法,javascript,arrays,algorithm,Javascript,Arrays,Algorithm,我有一个长度超过200000的巨大数组。我需要得到前10个值。我知道排序不是最好的解决方案。我尝试了以下解决方案: const sortBy = 'key'; const results = []; const m = 10; const N = array.length; while (array.length && results.length < m) { let currentMax = 0; let currentMaxIndex = 0;

我有一个长度超过200000的巨大数组。我需要得到前10个值。我知道排序不是最好的解决方案。我尝试了以下解决方案:

const sortBy = 'key';
const results = [];
const m = 10;
const N = array.length;

while (array.length && results.length < m) {
    let currentMax = 0;
    let currentMaxIndex = 0;
    array.forEach((record, i) => {
        if (record[sortBy] >= currentMax) {
            currentMax = record[sortBy];
            currentMaxIndex = i;
        }
    });
    results.push(...array.splice(currentMaxIndex, 1));
}
const sortBy='key';
常量结果=[];
常数m=10;
常数N=数组长度;
while(array.length&&results.length{
if(记录[sortBy]>=currentMax){
currentMax=记录[排序];
currentMaxIndex=i;
}
});
结果.push(…数组.splice(currentMaxIndex,1));
}
这里的数组是长度为200000的
数组

问题是,我认为如果
m
等于
N
,那么 将比排序本身花费更多的时间。我想知道是否有 是一个更好的解决方案,可以处理这两种情况


谢谢你的帮助,但实际问题是
m∈ (0,N)
m
可以取最大为
N
的任何值。那么,在哪一点上最好切换到内置的
排序

根据我的理解,当
m
达到
N
时,复杂性增加,排序是
m==N


我已经用@t-j-crowder提供的示例进行了测试。从100个参赛作品中选出前10名的测试


当在
m
中使用不同的值进行测试时,更快的算法将在
m==85
处变为
sort
。因此,我想知道是否有任何方法可以确定何时我们应该切换回排序,以在所有情况下都获得最佳性能。

您不需要对整个数组进行排序,只需按数字顺序插入前10个数组并删除任何其他条目:

vara=Array.from({length:100},()=>Math.floor(Math.random()*1000000));
var check=a.slice().sort((左,右)=>right-left).slice(0,10);
控制台日志(“检查”,检查);
函数检查结果(top10){
var n;
对于(n=0;n<10;++n){
如果(top10[n]!==检查[n]){
log(“在#“+n+”测试中出错,应为“+check[n]+”,应为“+top10[n]);
返回false;
}
}
返回true;
}
var-top10=[];
var截止=-无穷大;
var full=假;
变量n,len,值;
对于(n=0,len=a.length;n=截止){
//插入前10名
让发现=错误;
对于(设n=0;n
。作为控制台包装器{
最大高度:100%!重要;
}
函数限制排序(数组、排序比、限制){
常量结果=[];
//在数组*上迭代一次*
for(阵列常数){
//排除最终不在结果数组中的所有元素
if(result.length结果[0]){
//确定需要插入元素的位置(插入排序)
设insertAt=0;
while(insertAt限制)
结果:拼接(0,1);
}
}
返回结果;
}

这实现了上面提出的算法。

取数组的第一个
限制
元素,并“假设”它们是前10个。对其排序(微小)列表。遍历大数组中的其余元素。如果它大于您提取的最小元素,则删除该最小元素并将新元素插入其有序位置。继续,直到扫描整个数组。这基本上应该是
O(nm)
使用
n
作为输入的大小,
m
作为输出的大小。迭代,对照下一个值检查每个值,将最大值存储在
limit
size max数组中,并替换数组中的最小值,直到考虑到两种有效算法:K-select和使用K-size优先级队列排序不是最好的解决方案。你怎么知道?排序和切片前10名是最有效的算法,除非你使用选择算法(中间值的中值——按线性时间运行)这是一件复杂的事情,大多数时候麻烦比它的价值还多。@Redu你是在开玩笑吧?使用Quickselect比它的价值更麻烦?我的经验大不相同。文章并没有说它比它的价值更麻烦。在一个小数组中,是的。但是如果你有一百万个项目,排序将花费很多时间比使用Quickselect或简单的堆选择算法更长。28毫秒和358毫秒之间的差异绝对值得付出努力。如果(top10.length>10){top10.length=10;}这是做什么的?@AvcS它将数组修剪为10个元素。我认为,尽一切努力保持
top10
数组排序、拼接以及所有这些,这一定有点效率低下。你可以将先排序大数组然后将前10个元素与此进行切片的性能进行比较。@Redu:我非常非常怀疑拼接到
top1的效果0 将会接近排序200000元素数组的成本。但是,是的,无论如何,测量它。-)你的代码并不是非常低效,甚至与FF(神秘的例子)排序和切片一样。但是,由于您对一个包含
m
项的阵列进行了
n
多次检查,并且在该阵列上进行了条件拼接,因此效率确实不高
  function limitSort(array, sortBy, limit) {
    const result = [];
    // Iterate over the array *once*
    for(const el of array) {
      // Exclude all elements that are definetly not in the resulting array
      if(result.length < limit || el[sortBy] > result[0]) {
        // Determine the position were the element needs to be inserted (Insertion sort)
        let insertAt = 0;
        while(insertAt < result.length && result[insertAt][sortBy] < el[sortBy]) insertAt++;
        // Finally insert it
        result.splice(insertAt, 0, el);
        // If the results are getting to long, remove the lowest element
        if(result.length > limit)
          result.splice(0, 1);
      }
    }
    return result;
 }