0221

개발

[백준] 5635번 - 생일

문제 링크 : https://www.acmicpc.net/problem/5635

문제 탐색하기

1) 문제 분석

  • '이름 dd mm yyyy'와 같은 형식으로 주어진다.

  • 주어지는 생일은 올바른 날짜이며, 연/월/일은 0으로 시작하지 않는다.

  • 이름이 같거나, 생일이 같은 사람은 없다.

2) 가능한 시간복잡도

(1) 입력 처리

  • 전체 입력을 한 번에 받아서 N줄로 나눔 → O(N)

  • 각 줄마다 반복 처리 → O(N)

(2) 한 줄 처리

  • 공백 기준 split → O(1) (길이 4 고정)

  • Number 변환 → O(1)

  • 객체 생성 -> O(1)

(4) 전체 시간 복잡도

  • 각 줄마다 O(1) 작업을 N번 반복하므로 → O(N)

3) 알고리즘 선택 이유

  • 이 문제는 입력한 값을 배열로 저장하여 해당 배열 내에서의 연/월/일을 계산한 뒤, 제일 나이 많은 사람과 제일 나이 적은 사람을 추출하는 목적을 둔다.

  • 연/월/일에 따라서만 정렬하면, 입력도 고정 길이라 연산 비용이 매우 낮다.-> 따라서, 정렬 후 수학적 조건을 판단하는 방식이 직관적이고 효율적이다.

코드 설계하기

1. 실행 구조

1) 사용자 정보(이름, 일/월/연)을 입력 받는다.

2) 입력된 행 수만큼 반복하고, 공백을 기준으로 분리한다.

3) 분리된 각 값을 Member 클래스에 저장하여 생성한다.

4) 변환된 각 행의 배열을 연도, 월, 일 순으로 내림차순으로 정렬한다.

5) 결과값을 출력한다.

2. 고민이 되었던 부분

JavaScript
memberInfos.sort((a, b) => b.year - a.year || b.month - a.month || b.day - a.day);

처음에는 단순히 사용자의 연도만을 기준으로 정렬하면 된다고 생각했다. 그러나 곧 같은 연도를 가진 사용자가 있을 수 있다는 점을 떠올리게 되었고, 월과 일까지 고려해야 진짜 나이 순으로 정렬할 수 있다는 점을 인지하게 되었다. 이를 구현하기 위해 sort() 메서드를 어떻게 활용할 수 있을지 고민하던 중, 연 → 월 → 일 순으로 b - a 형식의 연산을 연결해 사용하면, 원하는 대로 내림차순 정렬, 즉 나이가 많은 순으로 정렬할 수 있다는 사실을 발견했다. 이 과정을 통해 정렬 로직에 대한 이해가 한층 깊어졌다.

정답 코드

JavaScript
// 사용 언어 : Javascript

const fs = require('fs');

// 입력을 한 줄씩 받아와 문자열 배열로 변환
// 첫 줄은 회원 수 N, 그 다음 줄부터는 [이름 일 월 년] 형식의 회원 정보
const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');

// Member 클래스 정의: 이름, 생년월일을 속성으로 가짐
class Member {
    constructor({ name, day, month, year }) {
        this.name = name;       // 이름
        this.day = day;         // 일
        this.month = month;     // 월
        this.year = year;       // 년
    }
}

// 회원 정보를 담을 배열
let memberInfos = [];

// 입력 줄의 두 번째 줄부터 끝까지 반복하며 Member 객체로 변환
for (let i = 1; i < input.length; i++) {
    const data = input[i].split(" "); // 공백 기준으로 [이름, 일, 월, 년] 분리
    const memberInfo = new Member({
        name : data[0],
        day: Number(data[1]),
        month: Number(data[2]),
        year: Number(data[3])
    });
    memberInfos.push(memberInfo); // Member 객체를 배열에 추가
}

// 생일이 가장 늦은(어린) 순으로 정렬
// 기준: 년도 내림차순 → 월 내림차순 → 일 내림차순
memberInfos.sort((a, b) => 
    b.year - a.year || 
    b.month - a.month || 
    b.day - a.day
);

// 가장 생일이 늦은(어린) 사람의 이름 출력
console.log(memberInfos[0].name);

// 가장 생일이 빠른(나이 많은) 사람의 이름 출력
console.log(memberInfos[memberInfos.length - 1].name);

마무리하며

이제는 정렬 관련 문제들이 어느 정도 익숙해졌다는 느낌이 든다. 특히 sort() 메서드를 사용하는 데에 있어 오름차순과 내림차순의 차이, 그리고 값이 동일할 때 || 연산자를 활용한 다중 기준 정렬 방식도 자연스럽게 이해하고 적용할 수 있게 되었다는 점이 뿌듯하다.

또한, 단순히 whydev에서 제공하는 문제만 푸는 데 그치지 않고, 스스로 결단했던 것처럼 solved.ac에 접속해 추가 문제를 찾아 풀고 있다는 점은 이전과 분명히 달라진 성장이라 생각한다. 지금까지 전체의 약 20% 정도를 진행한 상황이지만, 앞으로 남은 알고리즘 문제도 끝까지 성실히 풀어내고 싶다.