[백준 문제풀이] 20291번 파일 정리 (node.js)

방예서·2022년 8월 8일
0

코딩테스트 준비

목록 보기
31/37

20291 파일 정리

문제

친구로부터 노트북을 중고로 산 스브러스는 노트북을 켜자마자 경악할 수밖에 없었다. 바탕화면에 온갖 파일들이 정리도 안 된 채 가득했기 때문이다. 그리고 화면의 구석에서 친구의 메시지를 확인할 수 있었다.

바탕화면의 파일들에는 값진 보물에 대한 정보가 들어 있어. 하나라도 지우게 된다면 보물은 물론이고 다시는 노트북을 쓸 수 없게 될 거야. 파일들을 잘 분석해서 보물의 주인공이 될 수 있길 바랄게. 힌트는 “확장자”야.

화가 났던 스브러스는 보물 이야기에 금세 화가 풀렸고 보물의 정보를 알아내려고 애썼다. 하지만 파일이 너무 많은 탓에 이내 포기했고 보물의 절반을 보상으로 파일의 정리를 요청해왔다. 스브러스의 요청은 다음과 같다.

파일을 확장자 별로 정리해서 몇 개씩 있는지 알려줘
보기 편하게 확장자들을 사전 순으로 정렬해 줘
그럼 보물의 절반을 얻어내기 위해 얼른 스브러스의 노트북 파일 정리를 해줄 프로그램을 만들자!

입력

첫째 줄에 바탕화면에 있는 파일의 개수 NN이 주어진다. (1N50 0001 \leq N \leq 50\ 000)

둘째 줄부터 NN개 줄에 바탕화면에 있는 파일의 이름이 주어진다. 파일의 이름은 알파벳 소문자와 점(.)으로만 구성되어 있다. 점은 정확히 한 번 등장하며, 파일 이름의 첫 글자 또는 마지막 글자로 오지 않는다. 각 파일의 이름의 길이는 최소 33, 최대 100100이다.

출력

확장자의 이름과 그 확장자 파일의 개수를 한 줄에 하나씩 출력한다. 확장자가 여러 개 있는 경우 확장자 이름의 사전순으로 출력한다.

문제 풀이

// 백준 20291번 파일 정리

const fs = require("fs");
const input = fs.readFileSync("input.txt").toString().trim().split("\n");
const n = Number(input.shift());

const result = {};

for (let i = 0; i < n; i++) {
  let extension = input[i].split(".")[1];
  extension = extension.replace(/\r/g, "");
  result[extension] ? result[extension]++ : (result[extension] = 1);
}

let print = {};

Object.keys(result).sort().forEach((key) => {
    print[key] = result[key];
  });

let a = "";
for (el in print) {
  a += `${el} ${print[el]}\n`;
}
console.log(a);

입력 값을 . 을 기준으로 분리하여 뒤쪽의 문자열을 확장자로 취급한다.
해당 확장자를 key로, value는 횟수로 생각하여 지정해준다.



처음에 무작정 2차원 배열로 풀려고 includes, indexOf 등을 for문 내부에서 사용한 것이 시간 초과의 문제였던 것 같다.


// 배열로 풀어서 시간 초과난 풀이

let result = [];
let extensions = [];
let print = "";

for (let i = 0; i < input.length; i++) {
  let file = input[i].split("");
  if (i !== input.length - 1) file.pop();

  let extension = file.split(".")[1];
  let temp = [];

  if (extensions.includes(extension)) {
    result[extensions.indexOf(extension)][1]++;
  } else {
    temp.push(extension);
    temp.push(1);
    extensions.push(extension);
    result.push(temp);
  }
}

result.sort();
for (let i = 0; i < result.length; i++) {
  print += `${result[i][0]} ${result[i][1]}\n`;
}
console.log(print);

그저 편하게 쓰던 내장 함수... 였는데 자꾸 시간초과가 나서
생각해보면 결국 배열 안에서 있는지 찾거나 인덱스 가져오는 것인데 자바스크립트가 어쨌든 탐색 시간을 잡아먹는거였으니까 당연한 결과였다.

찾아보니 indexOf는 O(n) 시간복잡도를 갖고 있다고 본다.
만약에 자바스크립트가 O(n)의 시간복잡도로 탐색하고 있었다면 이 문제에서의 시간복잡도는 O(n^2)가 걸리는 것이니 n의 범위가 큰만큼 시간 초과가 난 것 같다.

다른 사람들의 풀이를 참고해 객체를 이용하였고, 시간 초과가 나니까 console.log를 한번만 해줄 수 있게 해주었다.








참으로 어렵도다...
시간 초과 때문에 너무 오래 걸린 문제.

profile
console.log('bang log');

0개의 댓글