[알고리즘] 완주하지 못한 선수

colki·2021년 2월 28일
1

완주하지 못한 선수 🏃‍♀️

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


마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.


◼ 제한사항

  • 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
  • completion의 길이는 participant의 길이보다 1 작습니다.
  • 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
  • 참가자 중에는 동명이인이 있을 수 있습니다.

◼ 입출력 예


👩‍🦰 오답노트


오답1

for문을 사용해서 배열의 인덱스로 값에 접근해서 비교하면 되겠구나 생각하고 코드를 써내려갔다. 하지만 결과는 3개중 2개만 성공이었다.

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


/*  3개 중 2개 성공

테스트 1
입력값 〉["leo", "kiki", "eden"], ["eden", "kiki"]
기댓값 〉"leo"
실행 결과 〉테스트를 통과하였습니다.

테스트 2
입력값 〉["marina", "josipa", "nikola", "vinko", "filipa"], ["josipa", "filipa", "marina", "nikola"]
기댓값 〉"vinko"
실행 결과 〉실행한 결괏값 "marina"이(가) 기댓값 "vinko"와(과) 다릅니다.

테스트 3
입력값 〉["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]
기댓값 〉"mislav"
실행 결과 〉테스트를 통과하였습니다.

*/

내가 작성한 코드는 participant배열과 completion배열을
앞에서부터 차례대로 비교하고, 다를 경우 값을 return하는 방식이었기 때문에
테스트2에서 "marina"와 같은 인덱스에 있는 "josipa"에서부터 다르다고
인식해서 바로 "marina"가 출력되었고 기댓값 "vinko"와 다를 수 밖에 없었다.


오답2

굳이 for문을 2개로 중첩할 필요가 없었다는 걸 깨달아서 for문은 하나로
사용했다. 처음 오답에서의 문제를 떠올리고, 배열vs배열로 순서대로 확인하는 방법이 아니라 participant의 요소가 completion배열에 있는지 확인하는 방법이 낫겠구나 해서 indexOf를 사용해서 아래와 같이 작성하였는데...

function solution(participant, completion) {
  for (let i=0; i<participant.length; i++) {
    if (completion.indexOf(participant[i], 0) === -1)
      return participant[i];
  }
}

/* 3개 중 2개 성공
테스트 1
입력값 〉["leo", "kiki", "eden"], ["eden", "kiki"]
기댓값 〉"leo"
실행 결과 〉테스트를participant에서는  통과하였습니다.

테스트 2
입력값 〉["marina", "josipa", "nikola", "vinko", "filipa"], ["josipa", "filipa", "marina", "nikola"]
기댓값 〉"vinko"
실행 결과 〉테스트를 통과하였습니다.

테스트 3
입력값 〉["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]
기댓값 〉"mislav"
실행 결과 〉실행한 결괏값 undefined이(가) 기댓값 "mislav"와(과) 다릅니다.

*/

허나 이번에도 테스트 한개는 통과하지 못했는데, 처음 오답때와는 달리
이번에는 테스트 2번은 통과했지만 3번은 실패했다 ☹

participant = ["mislav", "stanko", "mislav", "ana"]
completion = ["stanko", "ana", "mislav"]

중복값을 가지는 "mislav"때문에 같은 값이 없을 경우로 작성한
if (completion.indexOf(participant[i],0)===-1) 조건문이
성립할 수가 없다. -1이 아닌 경우에 대해서는 내가 else구문을 쓰지
않았고 true일경우에만 return문이 열리기 때문에
undefined로 출력된 것이다.


Solution🔅

오답2에서 사용한 방법은 중복된 값이 있을 때 사용할 수 없기 때문에 탈락.
오답1을 심화시켜서 머리를 쥐어짜다가
오답1에서 통과한 테스트 1, 3을 들여다 보았다.

테스트 1
입력값 〉["leo", "kiki", "eden"], ["eden", "kiki"]
기댓값 〉"leo"
실행 결과 〉테스트를 통과하였습니다.

테스트 3
입력값 〉["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]
기댓값 〉"mislav"
실행 결과 〉테스트를 통과하였습니다.

인덱스 순서대로 각 자리값을 비교할 때 participant의 [0]과 completion의 [0]를 가장 먼저 비교하는데,
completion의 [0]에 "leo"가 없기때문에 바로 "leo"가 출력될 수 밖에 없는 것이다.
그래서 테스트 3을 통과한 것도 사실 운이 좋았었다.
정답은 "mislav"로 정해져 있는데,
마침 completion[0]에 "stanko"가 위치했기 때문에 바로 출력된 것이다.
그래서 두 배열의 값을 같은 순서대로 오름차순/내림차순으로 정렬하고
비교한다면 같은 값은 넘어가고 다른 값에서 바로 return이 될 것이다.
array align javascrip로 구글링을 하면 반가운 우리의 mdn이 나온다.


Array.prototype.sort()

sort() 메서드는 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환하고,
문자열의 경우 오름차순으로 정렬을 해주는 메서드이다.
단, 숫자일 경우에는 그냥 사용했다가는 낭패를 볼 수 있다.

관련해서 내가 따로 적어둔 글을 보면 도움이 될 것이다.
sort()메서드 개념이해 포스팅 보기

ex)
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]


문제의 두 배열에 적용해보면


const participant = ["marina", "josipa", "nikola", "vinko", "filipa"];
const completion = ["josipa", "filipa", "marina", "nikola"];

console.log(participant.sort());
console.log(completion.sort());

//["filipa", "josipa", "marina", "nikola", "vinko"]
// ["filipa", "josipa", "marina", "nikola"]

()안에 조건을 명시하지 않았지만 같은 문자열타입의 배열 2개를 비교하므로 같은 오름차순으로 정렬되는 걸 볼 수 있다. 그리고 오답1 for문 앞에 sort메서드를 넣어보았다.

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

// 3개 중 3개 성공

드디어 3개 모두 성공이라는 결괏값을 받을 수 있었다. 야호 🐸

지금은 자바스크립트에 대한 이해와 지식이 얉아서 문법 하나 메서드 하나 검색을 하려고 키워드를 떠올리는 것도 어렵지만, 이렇게 하나하나 배워가는 경험이 쌓이고 쌓이다 보면 그 경험치로 레벨업할 수 있을거라고 믿는다.

programmers 코딩테스트

profile
매일 성장하는 프론트엔드 개발자

0개의 댓글