---
# System prepended metadata

title: '#2 Find Three Largest Numbers'
tags: [Easy, Searching]

---

# #2 Find Three Largest Numbers

###### tags:`Searching` `Easy`

## Problem
Write a function that takes in an array of at least three integers and, without sorting the input array, returns a sorted array of the three largest integers in the input array.
The function should return duplicate integers if necessary; for example, it should return `[10, 10, 12]` for an input array of `[10, 5, 9, 10, 12]`

### Sample Input
```javascript
array = [141, 1, 17, -7, -17, -27, 18, 541, 8, 7, 7]
```

### Sample Output
```javascript
[18, 141, 541]
```
<br>

:::spoiler **Optimal Space & Time Complexity**
```
O(n) time | O(1) space - where n is the length of the input array
```
:::

<br>

:::spoiler Hint 1
Can you keep track of the three largest numbers in an array as you traverse the input
array?
:::

<br>

:::spoiler Hint 2
Following the suggestion in Hint #1, try traversing the input array and updating the three largest numbers if necessary by shifting them accordingly.
:::

<br>


<hr/>

## Solutions

### Official 
![](https://i.imgur.com/vCghsig.png)
<br>

---

### Everyone's

Declare an answer array and update the value while iteraion

:::spoiler 月
```javascript=
/* Time: O(n), Space: O(1)
   n is the length of array
*/
function findThreeLargestNumbers(array) {
    const ans = [-Infinity, -Infinity, -Infinity];
    for (const num of array){
        if(num > ans[2]){
            [ans[0], ans[1]] = [ans[1], ans[0]];
            [ans[2], ans[1]] = [ans[1], ans[2]];
            ans[2] = num;
        }else if(num > ans[1]){
            [ans[0], ans[1]] = [ans[1], ans[0]];
            ans[1] = num;
        }else if(num > ans[0]){
            ans[0] = num;
        }
    }
    return ans
  }
```
:::

<br>

:::spoiler 東
```javascript=
// Time O(n) | Space O(1) - n is the length of input array
function findThreeLargestNumbers(array) {
  const ans = [array[0], array[1], array[2]];
  ans.sort((a, b) => a - b);
  for(let i = 3; i < array.length; i++){
    if(array[i] > ans[2]){
      [ans[0], ans[1], ans[2]] = [ans[1], ans[2], array[i]];
    } else if(array[i] > ans[1]){
      [ans[0], ans[1]] = [ans[1], array[i]];
    } else if(array[i] > ans[0]) ans[0] = array[i];
  }
  return ans;
}
```
:::

<br>

:::spoiler Hao
Solution A: use merge sort
(but this quesion ask us not to sort input array)
```javascript=
/**
 * Time complexity: O(nlogn) which n stands for array.length;
 * Space complexity: O(n) which n stands for array.length;
 */

const mergeSort = (array) => {
    const sortedArr = [Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY];

    for (let i = 0; i < array.length; i += 1) {
        let start = 0;
        let end = sortedArr.length - 1;

        while (end - start > 1) {
            const mid = Math.ceil((start + end)/2);

            if (array[i] > sortedArr[mid]) start = mid;
            else end = mid;
        }

        sortedArr.splice(start + 1, 0, array[i]);
    }

    return sortedArr.slice(1, -1);
}

function findThreeLargestNumbers(array) {
    return mergeSort(array).slice(-3);
}
```

Solution B: update `largestThree` in every iteration
```javascript=
/**
 * Time complexity: O(n) which n stands for array.length;
 * Space complexity: O(1);
 */

function findThreeLargestNumbers(array) {
    const largestThree = Array(3).fill(Number.NEGATIVE_INFINITY);
    
    for (let i = 0; i < array.length; i += 1) {
        let candidate = array[i];

        for (let j = largestThree.length - 1; j >= 0; j -= 1) {
            if (candidate > largestThree[j]) {
                [candidate, largestThree[j]] = [largestThree[j], candidate];
            };
        }
    }

    return largestThree;
}
```
:::

<br>


The most general approach(Better than official solution)

:::spoiler YC
```javascript=
/* 
  time: O(n) - where n is the length of the given array
  space: O(1)
*/

function findThreeLargestNumbers(array) {
  const LENGTH = 3;
  const ans = new Array(LENGTH).fill(Number.NEGATIVE_INFINITY);
  for(let num of array){
    for(let i = LENGTH - 1; i >= 0; i--){
      if(num > ans[i]){
        shiftPos(num, i, ans)
        ans[i] = num;
        break;
      }
    }
  }
  return ans;
}


function shiftPos(num, endPos, ans){
  for(let i = 0; i < endPos; i++){
    ans[i] = ans[i+1];
  }
}
```
:::

<br>


---

## Supplement / Discussion
