https://programmers.co.kr/learn/courses/30/lessons/42862
코딩테스트 연습 - 체육복
점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번
programmers.co.kr
1. 문제에 대한 이해
- 우리가 풀어야 할 문제는 무엇인가?
- 체육 수업을 듣기 위해서는 체육복이 있어야한다.
- 체육복 도난 당한 학생들이 여벌의 체육복이 있는 학생들한테 빌려서 체육 수업을 들을 수 있는 학생들은 총 몇명인가? - 주어진 자료는 무엇인가?
- n = 전체 학생 수
- lost = 체육복 도난 당한 학생들의 번호
- reverse = 여벌의 체육복이 있는 학생들의 번호 - 조건은 무엇인가?
- 전체 학생 수는 2명 이상 30명 이하이다.
- 체육복 도난 당한 학생 중에 중복되는 번호는 없다.
- 여벌의 체육복을 가진 학생 중에 중복되는 번호는 없다.
- 여벌 체육복을 가진 학생이 체육복 도난 당했으면 체육복이 한개 남기 때문에 빌려줄 수 없다.
- 여벌 체육복을 가진 학생은 자신의 번호 n-1 혹은 n+1 학생에게만 빌려줄 수 있다. - 숨겨진 조건이나 자료가 있는가? 그렇다면 그 것을 다른 방법으로 해석해보라.
- 여벌 체육복이 있는 학생의 총 체육복 개수는 2벌이다.
- 여벌 체육복이 있는 학생들은 무조건 체육 수업을 들을 수 있다.
2. 계획
- 전에 비슷한 문제를 알고 있는가?
- 코테 완주하지 못한 선수에서 요소를 찾고 찾은 요소는 배열에서 제거 시켰는데 이부분을 활용할 수 있으려나,,
- https://hxunz.tistory.com/167?category=1030034 - 이 문제를 푸는데 있어서 유용하게 쓸 수 있는 지식은 무엇인가?
- 이중반복문
- filter()
- reserve의 요소와 lost의 요소가 같다면
각각의 배열에서 해당 요소 제거 - 이걸 새로운 변수 newReserve, newLost 에 담아준다.
- 이제 이 둘의 배열을 반복문을 통해서 비교해보자
- 반복문은 reserve의 요소를 n-1 한것과 n+1 한 것 두번 이중으로 돌아야(?)할것이다.
- 우선, newReserve 요소가 전부 n-1일 경우를 계산해보자
- 만약 newReserve의 요소를 -1 했을 때 newLost에서 해당하는 숫자가 있다면
- newReserve와 newLost에서 각각 그 요소를 제거한다.
- 그 다음에 newReserve 요소가 전부 n+1인 경우
- 만약에 newReserve의 요소를 +1 했을 때 newLost에서 해당하는 숫자가 있다면
- newReserve와 newLost에서 각각 그 요소를 제거한다.
- 이때, newLost의 길이가 0이라면 (모두가 체육복을 빌려입은것이겠지,,)
- 전체 학생 수 n을 리턴
- newLost의 길이가 1이상이라면,
- 전체 학생 수 - 체육복 못 빌린 학생
- 여기서 체육복 못 빌린 학생은 위에서 체육복 빌려입고 거르고 걸러진 newLost의 길이이다.
3. 실행
- 풀이 계획을 실행하고, 각 단계가 올바른지 점검하라.
const solution = (n, lost, reserve) => {
let newLost = lost.filter(it => !reserve.includes(it)).sort();
let newReserve = reserve.filter(it => !lost.includes(it)).sort();
for (i = 0; i < newReserve.length; i++) {
for (j = 0; j < newLost.length; j++) {
if (newReserve[i] - 1 === newLost[j]) {
newReserve.splice(i, 1);
i--;
newLost.splice(j, 1);
j--;
}
if (newReserve[i] + 1 === newLost[j]) {
newReserve.splice(i, 1);
i--;
newLost.splice(j, 1);
j--;
}
}
}
return (newLost.length === 0) ? n : n - newLost.length;
};
test('체육수업에 참가할 학생 수 ', () => {
expect(solution(5, [2, 4], [1, 3, 5])).toEqual(5);
expect(solution(5, [2, 3], [3])).toEqual(4);
});
4. 반성
- 문제를 다른 방식으로 해결할 수 있는가?
- for 대신에 forEach나 map을 사용할 수도 있을것같다. - 결과나 방법을 어떤 다른 문제에 활용할 수 있는가?
- 다른 그리디 문제를 풀때나 두 개의 배열을 비교할때, 배열의 요소를 제거할때 활용할 수 있을것같다.
Facts & Findings
처음에는 계획 대강 세우고 filter()만 사용해서 교집합, 차집합;; 이용해서 풀려고 했다.
나 조차도 이해 안되는 변수명과 코드를 보니 뭔가 아니다 싶어서 다 갈아엎고
계획부터 머릿속으로 생각하면서 작성을 해 나갔고
계획대로 코드를 작성했고
테스트 코드를 실행해보니 통과가 됐다.
계획 단계의 중요성을 다시 한번 느끼게 되었다.
계획은 자세히 세울수록 문제 이해도 쉽고 구현하기에도 편한것같다.
귀찮아하지말고 계획을 잘 세우자!!
'코테연습' 카테고리의 다른 글
57. 부족한 금액 계산하기 Javascript (0) | 2022.06.08 |
---|---|
56. 폰켓몬 Javascript (0) | 2022.05.31 |
54. 모의고사 Javascript (0) | 2022.05.29 |
53. 문자열압축 Javascript (0) | 2022.05.27 |
52. K번째수 Javascript (0) | 2022.05.25 |
댓글