체육복
문제 링크
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 설명
점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다.
예를 들어 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.
전체 학생의 수 'n', 체육복을 도난당한 학생들의 번호가 담긴 배열 'lost', 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 'reserve'가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해 주세요.
제한 조건
- 전체 학생의 수는 2명 이상 30명 이하입니다.
- 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌의 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
- 여벌의 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.
입출력 예
n | lost | reserve | return |
5 | [ 2, 4 ] | [ 1, 3, 5 ] | 5 |
5 | [ 2, 4 ] | [ 3 ] | 4 |
3 | [ 3 ] | [ 1 ] | 2 |
입출력 예 설명
입출력 예#1
1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.
입출력 예#2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.
해결 과정
처음 빠르게 코드를 짜고 테스트 케이스 성공으로 제출하게 되면 대부분 실패하는 경우가 발생합니다. 이는 문제를 대충 읽은 경우가 많습니다. 자주 실패하는 케이스들에 대해서 알아보고 해결 방법도 같이 확인해 보겠습니다.
첫 번째로 여벌의 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이 부분을 무시하고 진행하게 되면 여분이 있는데 잃어버린 사람이 자기 체육복이 아닌 다른 사람의 체육복을 가져가게 됩니다. 그렇기 때문에 for loop을 돌리기 전에 미리 필터링하여 중복을 제거하고 돌리면 해결됩니다.
테스트 케이스: n = 13, lost = [ 1, 2, 5, 6, 10, 12, 13 ], reserve = [2, 3, 4, 5, 7, 8, 9, 10, 11, 12], Return = 11
두 번째로 'lost'는 항상 오름차순 list가 아닙니다. 문제를 제출했을 때 13번, 14번 케이스가 실패하는 경우가 그런 경우입니다. 먼저 오름차순 또는 내림차순으로 정렬해 주고 for loop을 진행하면 해결됩니다.
테스트 케이스: n = 5, lost = [ 4, 2 ], reserve = [ 3, 5 ], Return = 5
세 번째로 한 학생이 앞번호 학생과 뒷번호 학생 모두 빌릴 수 있는데 뒷번호 학생 거를 빌려 버려서 다음 번호 학생이 못 빌리는 경우가 발생하여 실패하는 경우입니다. 예를 들어 3번 학생이 2번 학생과 4번 학생에게 빌릴 수 있는 상황인데 4번 학생에게 빌려서 5번 학생은 빌릴 수 없는 상황입니다. 3번 학생이 2번에게 빌린다면 5번 학생은 4번 에게 빌릴 수 있게 됩니다.
이런 경우 lost 배열을 오름차순으로 pop 하여 진행한다면 앞번호 학생부터 확인하고 내림차순으로 pop 하여 진행한다면 뒷번호 학생부터 확인함으로써 해결됩니다.
def solution(n, lost, reserve):
answer = n - len(lost) # 전체 학생의 수 - 도난당한 학생의 수
lost = sorted(lost, reverse=True) # 앞번호 학생부터 pop을 하기 위한 내림차순
# 여벌이 있지만 도난 당한 친구는 결국 한 벌이 남기 때문에 제거 후 카운트
for i in range(1, n+1):
if(i in lost and i in reserve):
answer += 1
lost.remove(i)
reserve.remove(i)
# 도난 당한 친구가 없을때 까지 반복
while( len(lost) > 0 ):
l = lost.pop() # 도난당한 학생
# 앞번호 학생의 여벌여부 확인
if(l-1 in reserve):
reserve.remove(l-1)
answer += 1
# 뒷번호 학생의 여벌여부 확인
elif(l+1 in reserve):
reserve.remove(l+1)
answer += 1
return answer
'ALGORITHM > Programmers' 카테고리의 다른 글
[Python] programmers, 다음 큰 숫자 Lv.2 (feat.bin, count, 이진수) (4) | 2023.02.12 |
---|---|
[Python] programmers, 최솟값 만들기 Lv.2 (feat.sum, zip, sorted, 한줄) (13) | 2023.02.10 |
[Python] programmers, 폰켓몬 Lv.1 (feat.시간 초과, 해시, 한줄) (8) | 2023.02.06 |
[Python] programmers, 둘만의 암호 Lv.1 (feat.정규표현식) (4) | 2023.02.04 |
[Python] programmers, 기사단원의 무기 Lv.1 (feat.시간 초과) (12) | 2023.02.02 |