본문 바로가기

1일1알고리즘

완주하지 못한 선수 - sort(), return, break, includes, indexOf | 프로그래머스 코딩테스트 [자바스크립트]

 

코딩테스트 연습 - 완주하지 못한 선수

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

programmers.co.kr

참가자 배열과 완주자 배열을 줌. 과제는 완주하지 못한 선수 한 명의 이름을 찾아내기. 동명이인이 있을 수 있음. 

 

1. 첫 번째 시도 (실패)

function solution(participant, completion) {
    let answer;
    
    for (let i = 0; i < participant.length; i++) {
        if (!completion.includes(participant[i])) {
            answer = participant[i];
        }
    }
    
    return answer;
}

참가자 이름을 들고 완주자 목록에 있는지 확인하기.

동명이인이 없을 때는 맞지만 동명이인 있으면 틀려버림.

 

2. 두 번째 시도 (절반만 성공)

function solution(participant, completion) {
    let answer;
    
    for (let i = 0; i < participant.length; i++) {
        if (completion.includes(participant[i])) {
            let index = completion.indexOf(participant[i]);
            if (index > -1) {
                completion.splice(index, 1);
            }
        } else if (!completion.includes(participant[i])) {
            answer = participant[i];
        }
    }
    
    return answer;
}

동명이인 때문에 발생하는 문제를 없애려 시도.

참가자 이름을 완주자 목록에서 찾으면 완주자 목록에서 해당 이름을 삭제하는 방식으로 해결.

하지만

시간이 너무 오래 걸림.

 

3. 시간 줄이기 시도 (실패)

function solution(participant, completion) {
    let answer;
    
    for (let i = 0; i < participant.length; i++) {
        let index = completion.indexOf(participant[i]);
        
        if (index > -1) {
            completion.splice(index, 1);
        } else if (!completion.includes(participant[i])) {
            answer = participant[i];
        }
    }
    
    return answer;
}

if를 쓸데없이 두 번 돌리는 것 같아서 하나로 해결.

하지만 효율성 문제 여전히 존재.

 

4. 시간 줄이기 시도2 (정확성 문제 발생)

function solution(participant, completion) {
    let answer;
    const sortedParticipant = participant.sort();
    const sortedCompletion = completion.sort();
    
    for (let i = 0; i < participant.length; i++) {
        if (sortedParticipant[i] !== sortedCompletion[i]) {
            answer = sortedParticipant[i];
        } 
    }
    
    return answer;
}

검색하다가 sort()를 발견함. A to Z로 정렬해주는 기능.

위 방법들에서는 참가자 이름 하나마다 완주자 이름을 다 훑어야 했는데 sort()를 쓰면 처음 한 번만 정렬을 한 다음에 배열들을 나란히 놓고 인덱스 값만 비교하면 돼서 효율성 높아짐.

그러나

동명이인 문제 다시 발생.

 

답이 나오자마자 함수를 빠져나오지 않아서 문제가 생긴다고 분석.

 

참가자: [1, 2, 3, 3, 4, 5]

완주자: [1, 2, 3, 4, 5]

이런 사례라면 참가자[3], 즉 참가자 배열의 두 번째 3을 뱉어내야 하는데 참가자[4]와 참가자[5]도 값이 다른 탓에 결국 참가자 마지막 요소를 찍어냄.

break 필요.

 

5. 함수 빠져나오기 (드디어 성공)

function solution(participant, completion) {
    const sortedParticipant = participant.sort();
    const sortedCompletion = completion.sort();
    
    for (let i = 0; i < participant.length; i++) {
        if (sortedParticipant[i] !== sortedCompletion[i]) {
            return sortedParticipant[i];
        } 
    }
}

함수에서 return은 break 기능도 하기 때문에 return을 반복문 안으로 넣음. 문제가 지정해준 변수 answer도 그냥 없애버림.

 

6. break을 써보자 (실패)

break라는 게 있는 것만 알고 어떻게 쓰는지는 몰라서 추가로 시도해봄.

function solution(participant, completion) {
    let answer;
    const sortedParticipant = participant.sort();
    const sortedCompletion = completion.sort();
    
    for (let i = 0; i < participant.length; i++) { 
        if (sortedParticipant[i] !== sortedCompletion[i]) { break; }
        answer = sortedParticipant[i]; 
    }
    
    return answer;
}

일단 { break; }로 반복을 멈춘 다음에 뭔가를 하는구나.

아니 근데

동명이인이 있을 때만 결과값이 맞는 이상한 현상 발생.

하나 이전 결과값을 내보내나?

 

7. break을 써보자2 (성공)

function solution(participant, completion) {
    let answer;
    const sortedParticipant = participant.sort();
    const sortedCompletion = completion.sort();
    
    for (let i = 0; i < participant.length; i++) { 
        if (sortedParticipant[i] !== sortedCompletion[i]) { break; }
        answer = sortedParticipant[i + 1]; 
    }
    
    return answer;
}

answer에 sortedParticipant[i + 1]을 담았더니 정상 작동. 왜?

 

break

The break statement terminates the current loop, switch, or label statement and transfers program control to the statement following the terminated statement.

developer.mozilla.org

MDN 예시를 봐도 

let i = 0;

while (i < 6) {
  if (i === 3) {
    break;
  }
  i = i + 1;
}

console.log(i);
// expected output: 3
function solution(participant, completion) {
    let answer;
    const sortedParticipant = participant.sort();
    const sortedCompletion = completion.sort();
    
    for (let i = 0; i < participant.length;) { 
        if (sortedParticipant[i] !== sortedCompletion[i]) { break; }
        answer = sortedParticipant[i + 1]; 
        i += 1; 
    }
    
    return answer;
}

이렇게 i++를 밖으로 빼고 다른 방식으로 써보니 이해함.

break 시점에 sortedParticipant[i + 1]의 i는 아직 1이 더해지기 이전.