Crystal
Crystal

Reputation: 1505

Given an array of integers, find the second largest and second smallest within the array

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

Answers (9)

Sachin Devamore
Sachin Devamore

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

Raviteja
Raviteja

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

JpG
JpG

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

Mitul Panchal
Mitul Panchal

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

vinoth h
vinoth h

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

Hannes Leitner
Hannes Leitner

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

Majid Fouladpour
Majid Fouladpour

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

Bovard
Bovard

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

Vidul
Vidul

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

Related Questions