본문 바로가기

Algorithm/99클럽

[99클럽] 코딩테스트 스터디, 10일차 TIL - 비기너 (프로그래머스, 완주하지 못한 선수)

728x90

 

1. 문제풀이, 완주하지 못한 선수 (프로그래머스)

1) 문제

수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.

마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때,

완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해 주세요.

 

제한사항

- 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.

- completion의 길이는 participant의 길이보다 1 작습니다.

- 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.

- 참가자 중에는 동명이인이 있을 수 있습니다.

 

2) 해석

- 완주하지 못한 선수의 이름을 return

- 선수 배열, 완주한 선수 배열 주어짐

- 완주하지 못한 선수는 1명

- 동명이인이 있을 수 있음

 

- 완주한 선수 이름을 선수 배열에서 삭제 

 

 

3) 풀이

function solution(participant, completion) {    
    //선수 배열 obj
    const participantMap = new Map();
    
    for(let i=0; i<participant.length; i++){
        const name = participant[i]
        const prvValue = participantMap.get(name);
        
        participantMap.set(name, prvValue ? prvValue+1 : 1)
    }
    
    //완주한 선수 배열 빙글 돌기
    completion.forEach(name => {
        //선수 배열에 있으면 -1
        const preValue = participantMap.get(name);
        participantMap.set(name, preValue-1);
    })
    
    for(let entry of participantMap){
        if(entry[1] === 1) return entry[0]
    }
    
}

 

선수 배열과 완주한 선수 배열이 모두 주어진다고 해서 선수 배열을 돌면서 완주한 선수 이름을 삭제하면 되겠다고 생각했다.

그래서 처음엔 for문 안에서 includes를 해서 배열을 삭제하려고 했는데, 시간복잡도를 생각하면 map을 사용하는 게 좋겠다고 판단했다.

 

 

const participantMap = new Map();
    
for(let i=0; i<participant.length; i++){
    const name = participant[i]
    const prvValue = participantMap.get(name);
        
    participantMap.set(name, prvValue ? prvValue+1 : 1)
}

 

우선 for문을 이용해 map에 값을 저장해 준다.

[이름] : 횟수 이런 식으로 저장되도록 만들었다.

 

 

 

completion.forEach(name => {
    const preValue = participantMap.get(name);
    participantMap.set(name, preValue-1);
})

 

 

그리고 완주한 선수에 해당 이름이 있으면 count를 빼줬다.

 

 

for(let entry of participantMap){
    if(entry[1] === 1) return entry[0]
}

 

마지막으로 완주하지 못한 사람은 어차피 1명이기 때문에 map에서 값이 1인 것들을 reteurn 하도록 만들어줬다.

 

 

 

- 걸린 시간

 

2. 리팩토링

1) 수정

function solution(participant, completion) {    
    const participantMap = new Map();
    
    participant.forEach(name => {
        participantMap.set(name, (participantMap.get(name) || 0) + 1);
    });
    
    completion.forEach(name => {
        participantMap.set(name, participantMap.get(name) - 1);
    });
    
    for(let [name, count] of participantMap){
        if(count === 1) return name
    }
}

 

for문으로 작성했던 부분을 forEach로 수정해서 좀 더 깔끔하게 보이도록 만들었다.

그리고 for of에서 [name, count]로 좀 더 직관적으로 받아올 수 있도록 수정했다.

 

 

2) 다른 사람 코드 

function solution(participant, completion) {
    const map = new Map();

    for(let i = 0; i < participant.length; i++) {
        let a = participant[i], 
            b = completion[i];

        map.set(a, (map.get(a) || 0) + 1);
        map.set(b, (map.get(b) || 0) - 1);
    }

    for(let [k, v] of map) {
        if(v > 0) return k;
    }

    return 'nothing';
}

 

다른 사람 코드를 보다가 나랑 비슷한 방법인데 훨씬 깔끔한 코드를 발견했다.

map에 값을 저장할 때, count에 +와 -를 동시에 해서 반복문의 수를 줄였다.

 

리팩토링 할 때도 이런 식으로 해야겠다고는 생각못했는데,, 이런식으로 할 수도 있다는 걸 머리에 넣어둬야지..!

728x90
반응형