【问题标题】:How do I grab the two largest integers from a Javascript Array and return the value to the DOM?如何从 Javascript 数组中获取两个最大的整数并将值返回给 DOM?
【发布时间】:2016-05-16 22:41:09
【问题描述】:

我编写了一个解决方案来获取通过表单输入的整数列表。有用。它为您提供两个最大整数的总和并将其发布到 DOM 中。 但是,对于 100 万个整数的大型数组,它的效率不是很高。

如何改进此解决方案以提高效率。

App.js

 // This function reverses the order of the array and places the biggest numbers first
 function sortNumber(a, b) {
   return b - a;
 }


 // this function is used to ensure the user didn't enter any letters
 function getArray() {
   var alphaExp = /^[a-zA-Z]+$/;

   // This function takes the array, orders it, adds the sum of the two largest numbers and returns the value
   
   function sumOf(x) {
     
       // Sort the ary with the sortNumber function
       array.sort(sortNumber);
   
     // Then we add the two biggest numbers of the array and save it to the result variable.
     
       var result = array[0] + array[1];
     
       // Then we share the result with the user by updating the browser
       var myHeading = document.querySelector('h2');
       myHeading.textContent = "The sum of your two biggest numbers is: " + result;
       
     // Like a good student, it's important to show your work
       var showYourWork = document.querySelector('h3');
       showYourWork.textContent = array[0] + " + " + array[1] + " = " + result;
     }
     // This grabs the value of the input
   var arrayField = document.getElementById('arrayField').value;

   if (arrayField.match(alphaExp)) {
     
     // Fail if user enters letters
     var raiseError = document.querySelector('h5');
     raiseError.textContent = 'No not letters! We want numbers!!';
   } else {
     var array = JSON.parse("[" + arrayField + "]");
     if (arrayField.length < 2) {
       
       // If the user enters only 1 number, tell them to enter more!
       var raiseError = document.querySelector('h5');
       raiseError.textContent = 'Please enter atleast two numbers seperated by commas for us to add!'
     } else {
       
       // When the user enters a list of numbers, run the sumOf function.
       sumOf(arrayField);
       
       //Make the error go away
       var raiseError = document.querySelector('h5');
       raiseError.textContent = '';
     }
   }
 };

 // use an eventlistener for the event (This is where the magic happens)
 var subButton = document.getElementById('subButton');
 subButton.addEventListener('click', getArray, false);

【问题讨论】:

  • “效率不高”到底是什么意思?内置排序功能是一种很好的高效排序。您可能可以使用专门构建的基数排序做得更好,具体取决于输入值的性质。
  • 我指的是处理能力。我对 sort 函数的解释是,每次遇到一个并非紧接在前一个值之前的整数时,它都必须返回数组,如果它必须对一百万个整数进行排序,这似乎相当低效。跨度>
  • 不,排序是一个算法领域,已经被广泛研究了 60 或 70 年(甚至更长时间)。 .sort() 方法确实必须做一些工作来对数组进行排序,但请确信它非常有效。现在,如果您只需要提取两个顶部(或底部)值,则无需排序即可。
  • 您真的需要一个排序列表,还是仅仅确定两个最大的数字就足够了? (因为完全排序一百万个数字只是为了找到最大的两个听起来是一种非常低效的方法。)
  • 可以使用TypedArray吗?

标签: javascript arrays performance sorting


【解决方案1】:

您不必对其进行排序,只需线性搜索两个最大的:

编辑:下面的代码现在应该可以工作,并且比 OP 的代码要快。 OP 首先进行排序,这可以在 O(n log n) 中完成,假设是一个随机列表。我的代码使用c = 2 对O(cn) 中的列表进行线性搜索(这两个循环不是必需的,但很简单)。 ceil(n log n) = 2n 和 n 正整数的解决方案是 14,即对于每个长度超过 14 个条目的列表,下面的代码更快。例如:对于 100 万个条目,关系是 13,815,511 到 2,000,000,快了六倍多。您可以在一个循环中执行相同的操作,从而将运行时间减半(理论上,由于更好的局部性,它也稍微快一点)。

function maxtwo_wrong(a){
    var b1 = -Infinity;
    var b2 = -Infinity;

    for (var i=0; i < a.length; i++) {
        if (a[i] > b1) {
            b1 = a[i];
        }
    }
    for (var i=0; i < a.length; i++) {
        if (a[i] > b2 && a[i] < b1) {
            b2 = a[i];
        }
    } 
    return [b1,b2];
}

EDIT-2:maxtwo_wrong上面的代码似乎不符合要求,所以我又写了一个maxtwo_right并放在下面。 OP,请告诉我哪一个满足您的要求,以便我可以删除错误的。

EDIT-3:使它更简单和正确。

function maxtwo_right(a){
    var b1 = -Infinity;
    var b2 = -Infinity;

    for (var i=0; i < a.length; i++) {
        // If the current entry is bigger than variable b1
        // keep the old value in the variable b2 and set b1 to the
        // value of the current entry
        if (a[i] > b1) {
            b2 = b1;
            b1 = a[i];
        }
        // if the current entry equals b1 set the variable b2 to
        // the value of the current entry
        else if(a[i] === b1){
            b2 = a[i];
        }
    }
    // return the sum of the two variables as requested
    return b1 + b2;
}

【讨论】:

  • “未完全测试”,为什么不呢?
  • 因为我从来没有为不起作用的代码找到便宜的借口 ;-) 好吧,实际上:针对已排序的数组进行测试,但先进行排序,array.sort() 是就地的,所以我被自己愚弄了,现在脚上有个洞。
  • 唯一的问题是两个最大的数相同。
  • OP是最终的评委,但如果行为相同,结果应该是16。
  • @RyanJames Yepp,又搞错了,谢谢指出!虽然我的旧的没有73?您链接到的源代码中只有您自己的基于排序的算法。将帖子编辑为正确的代码,请检查它现在是否适合您。否则,我会冲洗并重复,直到您满意为止。
【解决方案2】:

我终于找到了一些时间坐下来解决这个问题。 我一直在看问题。

这是我的新解决方案

// This function adds the sum of the two largest integers of an array and returns the value
function topTwoInt(theArray) {
    var intArray = theArray;
    var highestInt = -Infinity;
    var secondHighestInt = -Infinity;
    var answer = 0;
    //Loop through the array
    for (var i=0; i < intArray.length; i++) {
        //grab the biggest int and assign it to the highestInt variable;
        if (intArray[i] > highestInt) {
            secondHighestInt = highestInt;
            highestInt = intArray[i]; 
        }
        //If the next number is equal too highestInt or greater than secondHighestInt
        //Make that number become the new secondHighestInt
        else if(intArray[i] === highestInt || intArray[i] > secondHighestInt) {
            secondHighestInt = intArray[i];
        }
    }
    answer = highestInt + secondHighestInt;
    return answer;
};

这个解决方案很大程度上受到@deamentiaemundi 的启发 谢谢大佬。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 2017-11-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    相关资源
    最近更新 更多