Reputation: 1505
I am trying to come up with a function that will take an array of integers and output the 2nd highest number and the 2nd smallest number. The function will take into account floats, duplicates, and negative numbers.
Two functions pass all the tests below except for test2.
var test1 = [7, 7, 12, 98, 106]
answer1 = {2nd Min: 12, 2nd Max: 98}
var test2 = [5, 23, -112, 6, 70, 70, -112]
answer2 = {2nd Min: 5, 2nd Max: 23}
var test3 = [-22, 22]
answer3 = {2nd Min: 22, 2nd Max: -22}
var test4 = [10, 89, 3]
answer = {2nd Min: 10, 2nd Max: 10}
var test5 = [10.4, -12.09, .75, 22]
answer3 = {2nd Min: 0.75, 2nd Max: 10.4}
/*/ \ \
---SOLUTION 1---
\ \ /*/
function secondGreatLow1(arr) {
//make copy of array because it will be spliced in the following functions
var arrCopy = arr.slice();
//push returned values of each function into this the answer array
var answer = []
answer.push(secondMin(arrCopy));
answer.push(secondMax(arrCopy));
return answer;
};
//helper function 1
var secondMin = function (arr){
var arrCopy = arr.slice();
//check length of array
if (arr.length == 2) {
return arr[1];
} else {
var min = Math.min.apply(null, arrCopy);
arrCopy.splice(arrCopy.indexOf(min), 1);
//check for duplicates
for (var i = 0; i < arrCopy.length; i++) {
if (arrCopy.indexOf(min) === -1) {
//.apply is used for arrays
return Math.min.apply(null, arrCopy);
} else {
arrCopy.splice(arrCopy.indexOf(min), 1);
return Math.min.apply(null, arrCopy);
}
};
}
};
//helper function 2
var secondMax = function (arr){
var arrCopy = arr.slice();
if (arr.length == 2) {
return arr[0];
} else {
var max = Math.max.apply(null, arrCopy);
arrCopy.splice(arrCopy.indexOf(max), 1);
//check for duplicates
for (var i = 0; i < arrCopy.length; i++) {
if (arrCopy.indexOf(max) === -1) {
return Math.max.apply(null, arrCopy);
} else {
arrCopy.splice(arrCopy.indexOf(max), 1);
return Math.min.apply(null, arrCopy);
}
};
}
};
/*/ \ \
---SOLUTION 2---
\ \ /*/
function secondGreatLow2 (numbers) {
var arr = withoutDuplicates(numbers);
arr.sort(function(a,b) { return a-b; });
return arr[1] + ' ' + arr[arr.length-2];
};
// helpers
var withoutDuplicates = function(arr) {
var out = [];
for(var i=0; i<arr.length; i++) {
if(i === 0 || arr[i] !== arr[i-1]) {
out.push(arr[i]);
}
}
return out;
};
Upvotes: 3
Views: 6708
Reputation: 1
let ar = [1,4,76,80,90,3,6,82];
var big = 0,sbig=0;
for(let i=0; i<ar.length;i++){
if(big < ar[i]) {
sbig = big;
big = ar[i]
continue;
}
if(sbig < ar[i]) {
sbig = ar[i];
}
}
console.log(sbig,big);
Upvotes: 0
Reputation: 1
C program for arrays to find second largest and second smallest in a array.
#include<stdio.h>
void main()
{
int arr[20];
int small,big,big2,small2;
int i,num;
printf("Enter Number of elements:");
scanf("%d",&num);
printf("Enter the elements: \n");
for(i=0;i<num;i++)
scanf("%d",&arr[i]);//Entering elements
big = arr[0];//For big in array
small = arr[0];// For small in array
for(i=0;i<num;i++)
{
if(arr[i]>big)
{
big2 = big;
big = arr[i];
}
if(arr[i]<small)
{
small2 = small;
small = arr[i];
}
}
printf("The biggest is %d\n",big);
printf("The smallest is %d\n",small);
printf("The second biggest is %d\n",big2);
printf("The second smallest is %d\n",small2);
}
#tej
Upvotes: 0
Reputation: 932
If array contains duplicates like nums = [2, 3, 6, 6, 5]
, the below solution works,
let sortedArray = new Set(nums.sort((a, b) => b - a ));
console.log('second smallest', [...sortedArray][sortedArray.size - 2])
console.log('second largest',[...sortedArray][1]);
Upvotes: 0
Reputation: 632
This is an easy and simple method for a second highest number but the problem is we could not get a number if there have duplicate exists in the array.
function getSecondLargest(nums) {
if(nums.length<2){
return nums;
}
var first=0;
var second=0;
for(var i=0; i<nums.length;i++)
{
if(nums[i]>first)
{
second = first;
first = nums[i]
}
else(nums[i]>second && nums[i]!=first)
{
second = nums[i];
}
}
return second;
}
Upvotes: 0
Reputation: 531
Glad you have found the solution.I am posting this for those who are searching for a simpler solution.This would run on O(n) time.
var fl = arr[0],sl = arr[0];
var fs = Infinity,ss = Infinity;
//find the largest and smallest.
for(var i = 0;i < arr.length;i ++) {
if(arr[i] > fl) fl = arr[i];
if(arr[i] < fs) fs = arr[i];
}
//let us assume smallest is second largest and vice versa.
sl = fs;
ss = fl;
//find second smallest and largest.
for(var i = 0;i < arr.length;i ++) {
if(arr[i] < fl && arr[i] > sl) sl = arr[i];
if(arr[i] > fs && arr[i] < ss) ss = arr[i];
}
console.log("first and second largest : ",fl,sl);
console.log("first and second smallest : ",fs,ss);
Upvotes: 0
Reputation: 121
This would also work and it appears do be faster (no sorting). What do you guys think?
var secondMax = function(arr){
return Math.min(...arr.reduce((acc, val) =>
(val > Math.min(...acc)) ? [Math.max(...acc), val] : acc
, [-Infinity, -Infinity]))
}
var secondMin = function(arr){
return Math.max(...arr.reduce((acc, val) =>
(val < Math.max(...acc)) ? [Math.min(...acc), val] : acc
, [Infinity, Infinity]))
}
var unique = function(arr) {
return arr.filter((value, index, arr) =>
arr.indexOf(value) === index
)
}
var arr = [7, 7, 12, 98, 106, 106];
console.log(secondMin(unique(arr)));// => 12
console.log(secondMax(unique(arr)));// => 98
console.log(secondMin(arr));// => 7
console.log(secondMax(arr));// => 106
Upvotes: 0
Reputation: 30242
function get_seconds(a) {
var b = uniq(a); // remove duplicates and sort
var l = b.length;
return [b[1], b[l-2]];
}
Check full tests below:
var tests = {
"case1": {
"input": [7, 7, 12, 98, 106],
"output": [12, 98]
},
"case2": {
"input": [5, 23, -112, 6, 70, 70, -112],
"output": [5, 23]
},
"case3": {
"input": [-22, 22],
"output": [22, -22]
},
"case4": {
"input": [10, 89, 3],
"output": [10, 10]
},
"case5": {
"input": [10.4, -12.09, .75, 22],
"output": [0.75, 10.4]
}
};
function do_tests() {
var res, logs = '',
j_exp, j_res;
$.each(tests, function(c, io) {
j_exp = JSON.stringify(io.output);
res = get_seconds(io.input);
j_res = JSON.stringify(res);
if (j_res == j_exp) {
logs += '<div class="success">' + c + ' passed.</div>';
} else {
logs += '<div class="failed">' + c + ' failed. Expected: ' + j_exp + ', Got: ' + j_res + '</div>';
}
});
$("#log").html(logs);
}
function get_seconds(a) {
var b = uniq(a);
console.log(b, a);
var l = b.length;
return [b[1], b[l - 2]];
}
function uniq(a) {
return a.sort(sortNumber).filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
})
}
function sortNumber(a, b) {
return a - b;
}
div#log {
font-family: monospace;
}
div#log > div {
padding: 4px;
margin: 2px;
}
.success {
color: green;
}
.failed {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="do_tests();">Run tests</button>
<div id="log"></div>
Upvotes: 2
Reputation: 1195
In your second solution, your withoutDuplicates
function appears to operate on the assumption that the list is sorted (checking for duplicates by comparing an element to the previous element); however, in secondGreatLow2
, you call withoutDuplicates
without performing some sort of sorting.
If you changed the order of those two lines, solution #2 looks valid assuming you don't have any floating point mismatches, ie 3.9999999999997 != 3.99999999998
Upvotes: 3
Reputation: 10528
Not performance efficient for large arrays, but concise:
var a = [5, 23, -112, 6, 70, 70, -112], b = [];
// remove duplicates
b = a.filter(function (item, pos) {
return a.indexOf(item) == pos;
});
// sort
b.sort(function (a, b) {
return a > b;
});
console.log(b[1]); // 2nd min:12
console.log(b[b.length-2]); // 2nd max:12
Upvotes: 2