## 🌟 문제 [코딩테스트 연습 - 완주하지 못한 선수 \| 프로그래머스 스쿨](https://school.programmers.co.kr/learn/courses/30/lessons/42576) 마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 구하는 문제. ## 🌟 풀이 동명이인이 있을 수 있기 때문에 각 이름의 등장 횟수도 함께 세어줘야 했다. Map을 이용해서 이름의 등장 횟수와 이름을 매핑해주었다. 재밌었던 것은 이 문제를 2개월 전에 풀었을 때에는 completion을 기준으로 Map을 만들어서 풀었었는데, 이번에 풀 때에는 participant를 기준으로 Map을 만들어서 풀었다는 점이었다. ### completion을 기준으로 Map 만들기 "완주자 명단을 먼저 만들어두고, 참가자를 하나씩 대조하면서 명단에 없는 사람을 찾자." - completion을 순회하면서 Map에 완주자 정보를 저장하고 - participant를 순회하면서 Map에 없거나 카운트가 0인 사람 찾기 ```javascript function solution1(participant, completion) { // 1. completion으로 map 만들기 const map = new Map(); for (const person of completion) { if (map.has(person)) { map.set(person, map.get(person) + 1); } else { map.set(person, 1); } } // 2. participant 돌면서 map에 없는 사람 찾기 for (const person of participant) { if (!map.has(person) || map.get(person) === 0) { return person; } else { map.set(person, map.get(person) - 1); } } return ""; // 모든 사람이 완주했을 경우 (문제 조건상 발생하지 않음) } ``` ### participant를 기준으로 Map 만들기 "전체 참가자를 먼저 세어두고, 완주한 사람을 하나씩 지웠을 때 남은 한 사람이 미완주자" - participant를 순회하며 Map에 참가자 정보 저장 - completion을 순회하며 완주한 사람의 카운트 감소 - Map을 순회하며 카운트가 0보다 큰 사람 찾기 ```javascript function solution2(participant, completion) { // 참여자 맵 초기화 const participantMap = new Map(); // key: 이름, value: 해당하는 선수 수 for (const name of participant) { if (participantMap.has(name)) { participantMap.set(name, participantMap.get(name) + 1); } else { participantMap.set(name, 1); } } // 완주자 확인 for (const name of completion) { participantMap.set(name, participantMap.get(name) - 1); } // 완주하지 못한 선수 확인 for (const [name, count] of participantMap) { if (count > 0) return name; } return ""; // NEVER } ``` ### 비교? completion 기준으로 Map을 만드는 방법과 participant 기준으로 Map을 만드는 방법의 가장 큰 차이는 언제 판단해서 반환하느냐에 있는 것 같다. - completion 기준: participant를 순회하는 중간에 바로 찾아서 반환 - participant 기준: 모든 데이터를 처리한 후에 결과를 찾음 비록 for문의 개수 차이가 있긴 하지만 worse case를 기준으로 하더라도 둘 다 시간복잡도가 O(N)이기 때문에 성능상 차이는 크게 없을 것 같다...!