민혁이의 IT스토리

[프로그래머스/JS] - 체육복 본문

알고리즘/코딩테스트

[프로그래머스/JS] - 체육복

FE_Minhyuk 2026. 4. 27. 16:30
문제 설명

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 체육 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.
전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

제한 사항

- 전체 학생의 수는 2명 이상 30명 이하입니다.
- 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
- 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다.
- 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

 

 

출력 예 

 

 

문제 요약

도난당한 학생(lost)이 인접한 번호의 여벌 체육복을 가진 학생(reserve)에게 옷을 빌려, 체육 수업을 들을 수 있는 최대 학생 수를 구하는 문제입니다. 단, 여벌을 가져온 학생이 도난을 당했다면 본인이 입어야 하므로 남에게 빌려줄 수 없다는 예외 처리가 핵심입니다.

해결 방법: 배열 메서드 활용과 탐욕법

이 문제는 자바스크립트의 배열 메서드(filter, includes, findIndex, splice)를 적절히 활용하여 Greedy로 접근하는 것이 좋습니다.

  1. 전처리 (교집합 제거 및 정렬): 여벌을 가져왔지만 도난당한 학생은 남에게 빌려줄 수 없으므로 filter()와 includes()를 사용하여 lost와 reserve 양쪽 배열에서 모두 제외해 줍니다. 이후, 작은 번호의 학생부터 순서대로 처리해야 최적의 해를 구할 수 있으므로 .sort((a, b) => a - b)를 통해 오름차순으로 정렬합니다. (JS에서는 숫자 정렬 시 비교 함수를 꼭 넣어주어야 합니다.)
  2. 인접 요소 탐색 (앞번호 우선): 진짜 도난당한 학생 배열(actualLost)을 순회하며, 여벌이 있는 학생 배열(actualReserve)에 빌려줄 수 있는 친구(자신의 번호 - 1 또는 자신의 번호 + 1)가 있는지 findIndex()로 찾습니다. 이때 앞번호 친구를 먼저 찾는 것이 더 많은 학생에게 빌려줄 수 있는 탐욕법의 핵심입니다.
  3. 배열 업데이트: 체육복을 빌려주는 데 성공했다면(findIndex !== -1), 한 명이 중복해서 여러 명에게 빌려주는 것을 막기 위해 splice() 메서드를 사용하여 해당 학생을 actualReserve 배열에서 제거해 줍니다.

 

제출 코드

function solution(n, lost, reserve) {
    // 1. 전처리: 여벌이 있는데 도난당한 학생 제외 및 오름차순 정렬
    const actualLost = lost.filter(l => !reserve.includes(l)).sort((a, b) => a - b);
    const actualReserve = reserve.filter(r => !lost.includes(r)).sort((a, b) => a - b);

    let count = 0; // 체육복을 빌린 학생 수
    
    for (let i = 0; i < actualLost.length; i++) {
        const student = actualLost[i];
        
        // 2. 앞번호 친구부터 먼저 찾아보기 (탐욕법)
        const lendIndex = actualReserve.findIndex(r => r === student - 1 || r === student + 1);
        
        if (lendIndex !== -1) {
            count++;
            // 3. 빌려준 사람은 명단에서 1명 제거
            actualReserve.splice(lendIndex, 1);
        }
    }
    
    // 전체 학생 수 - (진짜 잃어버린 학생 수 - 옷을 새로 빌린 학생 수)
    return n - (actualLost.length - count);
}

 

 


💡 회고 (Retrospective)

 

파이썬으로 알고리즘을 풀 때는 리스트 컴프리헨션이나 내장 함수로 쉽게 처리하던 것들을 자바스크립트로 구현하려니 초기엔 낯설었습니다. 하지만 이번 문제를 통해 JS의 대표적인 배열 메서드인 filter, findIndex, splice의 활용법을 확실히 익힐 수 있었고, 특히 JS에서 숫자 배열을 정렬할 때는 .sort((a, b) => a - b) 처리가 필수라는 점을 뼈저리게(!) 배웠습니다.