I've written a solution to take a list of integers entered through a form. It works. It gives you the sum of the two largest integers and posts it in the DOM. However, it's not very efficient for large arrays of say 1 million integers.
How can I improve this solution to be more efficient.
// 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);
You don't have to sort it, just search linearly for the two biggest ones:
EDIT: the code below should work now and is asymptotically faster than the OP's code. The OP does sorting first which can be done in O(n log n), assuming a random list. My code does a linear search through the list in O(cn)
with c = 2
(the two loops are not necessary but simple). The solution for ceil(n log n) = 2n
with n
a positive integer is 14, that is for every list longer than 14 entries the code below is faster. E.g.: for one million entries the relation is 13,815,511 to 2,000,000, more than six times faster. You can do the same thing in a single loop which halves the runtime (theoretically, but it is also a tiny bit faster because of the better locality).
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: The code above maxtwo_wrong
seems not to fit the requirements, so I wrote another one maxtwo_right
and put it below. Please, OP, tell me which one fulfills your requirements such that I can delete the wrong one.
EDIT-3: made it simpler and correct.
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;
}
I finally found some time to sit down and work this one out. I was looking at the problem all wrong.
Here is my new solution
// 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;
};
This solution is largely inspired by @deamentiaemundi Thanks man.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With