점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.
전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.
| n | lost | reserve | return |
|---|---|---|---|
| 5 | [2, 4] | [1, 3, 5] | 5 |
| 5 | [2, 4] | [3] | 4 |
| 3 | [3] | [1] | 2 |
for(let i = 0; i < reserve.length; i++){
if(lost.includes(reserve[i])){
// 체육복을 도난 당했는데 여분도 들고 온 학생이 있는지 여무 확인
count_p++
count_m++ // 만약 있다면 count에 더하고
lost[lost.indexOf(reserve[i])] = 'x'
// 그 학생은 문자 'x'로 바꿔서 이후 계산에 관여되지 않게
reserve[i] = 'x'
}
}
for(let i = 0; i < reserve.length; i++){ // 여분체육복을 가져온 학생들 배열을 반복문
let A = reserve[i]
// 본인 다음 번호 학생에게 우선적으로 빌려주고 이전번호 학생도 조건이 맞으면 빌려줄 때
if(lost.includes(A+1) || (lost.includes(A-1) && !reserve.includes(A-2))){
count_p++
}
// 본인 이전 번호 학생에게 우선적으로 빌려주고 다음번호 학생도 조건이 맞으면 빌려줄 때
if(lost.includes(A-1) || (lost.includes(A+1) && !reserve.includes(A+2))){
count_m++
}
}
console.log(count_p,count_m)
// 앞쪽 우선 뒤쪽 우선 중 더 큰 것에 잃어버리지 않은 학생 수를 더해 return
return count_p >= count_m ? count_p + safe : count_m + safe
}
이 문제는 풀기 위해서 직접 손으로 종이에 테스트 케이스를 생각해 메모해가며 풀었다. 그 결과 여분의 체육복을 가져온 학생이 자신의 다음번호 학생에게 체육복을 먼저 줄 경우와 이전번호 학생에게 우선적으로 줄 경우의 값이 다르다는 것을 알게되었다. 그래서 두 케이스 모두 구해서 더 큰 값에 잃어버리지 않은 학생들의 수를 더하여 return 하였다.
그런데 자꾸 통과하지 못하는 케이스가 있어 확인해봤더니, 여분 옷을 가져온 학생이 도난당했을 때의 케이스 때문이었다. 처음에 실패했을 때에는 아래의 반복문에서 다른 학생들에게 빌려주기 전에 자신의 번호와 같은 lost 값이 있다면 빌려주도록 했는데, 이렇게 했더니 자신의 반복문 차례가 되기 전 학생에게서 먼저 빌리게 되는 경우가 생겨 통과하지 못한 케이스가 생긴 것이었다. 그래서 별도의 for문으로 먼저 이 케이스를 모두 해결하고나서 기존의 for문을 실행하는 것으로 통과했다.