The most straightforward implementation, without modifying the original array, is to iterate and track the biggest and next biggest:
function nextBiggest(arr) {
let max = -Infinity, result = -Infinity;
for (const value of arr) {
const nr = Number(value)
if (nr > max) {
[result, max] = [max, nr] // save previous max
} else if (nr < max && nr > result) {
result = nr; // new second biggest
}
}
return result;
}
const arr = ['20','120','111','215','54','78'];
console.log(nextBiggest(arr));
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Variations
The behaviour of returning -Infinity if there's no next maximum value distinct from the maximum value in a non-empty array can be modified at the end of the function, depending on the requirements.
Same as maximum
return result == -Infinity ? max : result;
For an empty array, this will return -Infinity as before, but would otherwise return the same value as the maximum if no next distinct maximum is found.
Return null
return result == -Infinity ? null : result;
Same as above, but the return value of null is more indicative of the nonexistence of a next distinct maximum.
The most straightforward implementation, without modifying the original array, is to iterate and track the biggest and next biggest:
function nextBiggest(arr) {
let max = -Infinity, result = -Infinity;
for (const value of arr) {
const nr = Number(value)
if (nr > max) {
[result, max] = [max, nr] // save previous max
} else if (nr < max && nr > result) {
result = nr; // new second biggest
}
}
return result;
}
const arr = ['20','120','111','215','54','78'];
console.log(nextBiggest(arr));
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Variations
The behaviour of returning -Infinity if there's no next maximum value distinct from the maximum value in a non-empty array can be modified at the end of the function, depending on the requirements.
Same as maximum
return result == -Infinity ? max : result;
For an empty array, this will return -Infinity as before, but would otherwise return the same value as the maximum if no next distinct maximum is found.
Return null
return result == -Infinity ? null : result;
Same as above, but the return value of null is more indicative of the nonexistence of a next distinct maximum.
Original answer
var secondMax = function (){
var arr = [20, 120, 111, 215, 54, 78]; // use int arrays
var max = Math.max.apply(null, arr); // get the max of the array
arr.splice(arr.indexOf(max), 1); // remove max from the array
return Math.max.apply(null, arr); // get the 2nd max
};
demo
Update 1
As pointed out by davin the performance could be enhanced by not doing a splice but temporarily replacing the max value with -Infininty:
var secondMax = function (arr){
var max = Math.max.apply(null, arr), // get the max of the array
maxi = arr.indexOf(max);
arr[maxi] = -Infinity; // replace max in the array with -infinity
var secondMax = Math.max.apply(null, arr); // get the new max
arr[maxi] = max;
return secondMax;
};
Anyway, IMHO the best algorithm is Jack's. 1 pass, with conversion to number. Mine is just short, using builtin methods and only wanted to provide it as an alternative, to show off all the different ways you can achieve the goal.
Update 2
Edge case with multiple values.
As comments pointed it out: this solution "does not work" if we have an array like [3, 3, 5, 5, 5, 4, 4].
On the other hand it would be also a matter of interpretation what we would consider "the 2nd largest element".
In the example we have:
- 3 elements with the largest value (5) at indices: 2,3,4
- 2 elements with the second largest value (4) at indices: 5,6
- 2 elements with the second smallest value (3) at indices: 1,2
The 2nd largest element could be interpreted as:
- the 2nd (largest element) - 5 at index 3 - assuming that there is an order, and that we aim for a unique value
- the (2nd largest) element - 4 at index 5 - assuming that there is an order, and that we aim for a unique value
Videos
Make a clone of your original array using .slice(0) like :
var temp_arr = arr.slice(0);
Then sor it so you get the second largest value at the index temp_arr.length - 2 of your array :
temp_arr.sort()[temp_arr.length - 2]
Now you could use indexOf() function to get the index of this value retrieved like :
arr.indexOf(second_largest_value);
var arr = [23, 21, 34, 34];
var temp_arr = [...new Set(arr)].slice(0); //clone array
var second_largest_value = temp_arr.sort()[temp_arr.length - 2];
var index_of_largest_value = arr.indexOf(second_largest_value);
console.log(second_largest_value);
console.log(index_of_largest_value);
Using ES6 Set and Array.from
const secondLargest = (arr) => Array.from([...new Set(arr)]).sort((a,b) => b-a)[1]
Above function removes duplicate elements using Set and returns the second largest element from the sorted array.