본문 바로가기
✅ 문제풀이

BOJ-백준 2108번 통계학 Node.js

by dogfoot.dev 2024. 1. 16.
728x90
728x90

BOJ-백준 2108번 통계학 Node.js 문제 풀이와 반례 입니다.

링크 : https://www.acmicpc.net/problem/2108

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

 

 

 

✅ Node.js 정답 코드 입니다. 더보기 클릭!

더보기
const fs = require("fs");

const input = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n")
  .map((num) => parseInt(num));


const n = input.shift();
const nums = input.sort((a, b) => a - b);

const avr = Math.round(input.reduce((acc, num) => (acc += num), 0) / n);
console.log(avr.toString());

console.log(nums[Math.floor(n / 2)].toString());

let max = 0;

const mapp = new Map();

for (let i of nums) {
  if (mapp.get(i)) {
    mapp.set(i, mapp.get(i) + 1);
  } else {
    mapp.set(i, 1);
  }
  if (mapp.get(i) > max) max = mapp.get(i);
}

let frq = [];
for (let i of new Set(nums)) {
  if (mapp.get(i) == max) frq.push(i);
}

frq.length > 1 ? console.log(frq[1]) : console.log(frq[0]);

const max_n = nums[n - 1];
const min_n = nums[0];
console.log((max_n - min_n).toString());

 

📌 해설

최빈값을 구하는 것이 가장 핵심이었던 문제였습니다. 

추가로 주의해야 할 부분은 반올림, 그리고 -0 으로 출력되지 않도록 하는 것에 유의하면 좋습니다. 

 

1. 

const fs = require("fs");

const input = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n")
  .map((num) => parseInt(num));


const n = input.shift();
const nums = input.sort((a, b) => a - b);

 

입력받기

 

 

2. 

const avr = Math.round(input.reduce((acc, num) => (acc += num), 0) / n);
console.log(avr.toString());

산술평균 출력

reduce 로 합산을 구하고 입력 받은 수의 총 갯수 n 으로 나눕니다. 

Math.round 로 반올림 -> toString() 10진수로 변환해줍니다. 

예제 4) input

3
0
0
-1

산술평균을 구하면 (0 + 0 + (-1)) / 3 = -0.333333...  이고,

첫째 자리에서 반올림하면 0입니다. 그러나 toString() 으로 변환하지 않고 출력하면 -0으로 출력하게 됩니다. 

 

3. 

console.log(nums[Math.floor(n / 2)].toString());

중앙값 출력 

 

 

4.

let max = 0;

const mapp = new Map();

for (let i of nums) {
  if (mapp.get(i)) {
    mapp.set(i, mapp.get(i) + 1);
  } else {
    mapp.set(i, 1);
  }
  if (mapp.get(i) > max) max = mapp.get(i);
}

let frq = [];
for (let i of new Set(nums)) {
  if (mapp.get(i) == max) frq.push(i);
}

frq.length > 1 ? console.log(frq[1]) : console.log(frq[0]);

최빈값 출력 

1. 각 숫자가 나온 횟수를 세고 map 객체에 저장합니다. 

2. 가장 많이 나온 횟수를 max 에 저장합니다. 

3. 최빈값이 여러개일때 최빈값중 두번째로 작은 값을 출력하기 위해 frq 이라는 배열에 최빈값을 모두~ push 해줍니다. 

4. 최빈값을 넣은 frq 배열의 길이를 확인하고 배열 길이가 2 이상이면 두번째로 작은 값 frq[1] 을 출력, 아니면 frq[0]을 출력합니다. 

 

5.

const max_n = nums[n - 1];
const min_n = nums[0];
console.log((max_n - min_n).toString());

범위

최댓값과 최솟값의 차이를 구합니다. 

 

 

 

 

📌 오답노트

더보기

시간초과

const mapp = new Map();
const sett = new Set(nums);

for (let i of sett) {
  const num_cnt = sorted.reduce((cnt, num) => cnt + (num == i), 0);
  mapp.set(i, num_cnt);
  if (num_cnt > max) max = num_cnt;
}

 

Map() 객체를 사용하겠다는 아이디어는 쉽게 떠올랐으나, 

for 문 안에서 reduce 를 써서 시간초과가 났다. 

 

이 부분을

const mapp = new Map();
const sett = new Set(nums);

for (let i of sett) {
  if (mapp.get(i)) {
    mapp.set(i, mapp.get(i) + 1);
    if (mapp.get(i) > max) max = mapp.get(i);
  } else {
    mapp.set(i, 1);
  }
}

로 바꾸어 시간초과를 해결하였다. 

 

 

 

📌 반례

input : 

5
0
0
1
1
3

 

 

output :

1
1
1
3

 

 

 

 

 

::

 

 

728x90
반응형