티스토리 뷰

출처:  https://programmers.co.kr/learn/courses/30/lessons/42576

문제 설명

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

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

제한사항

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

입출력 예

participant completion return
["leo", "kiki", "eden"] ["eden", "kiki"] "leo"
["marina", "josipa", "nikola", "vinko", "filipa"] ["josipa", "filipa", "marina", "nikola"] "vinko"
["mislav", "stanko", "mislav", "ana"] ["stanko", "ana", "mislav"] "mislav"

입출력 예 설명

예제 #1
"leo"는 참여자 명단에는 있지만, 완주자 명단에는 없기 때문에 완주하지 못했습니다.

예제 #2
"vinko"는 참여자 명단에는 있지만, 완주자 명단에는 없기 때문에 완주하지 못했습니다.

예제 #3
"mislav"는 참여자 명단에는 두 명이 있지만, 완주자 명단에는 한 명밖에 없기 때문에 한 명은 완주하지 못했습니다.

 

나의 풀이

첫번째 시도 (효율성 테스트 실패) 

let answer;

    for(let i=0;i<participant.length;i++){
        for(let j=0; j<completion.length;j++){
            if(participant[i]==completion[j]){
                participant[i]=undefined;
                completion[j]=undefined; 
                break; 
            }
        }
    }
    for(let i=0;i<participant.length;i++){
        if(participant[i]!=undefined){
            answer=participant[i];
            break;
        }   
    }

손이 가는 대로 코드 썼다가 실패했다. 이중 for문 때문에 효율성 테스트를 통과하지 못했다. 실패하고 나서 제한 사항을 보니까 입력되는 배열이 최대 10만이다. 이걸 이중 for문으로 돌렸으니 100억 번인가? 암튼 엄청 돌려야 된다.

그리고 또 아래에 for문을 써서 최대 10만 번 더 돌려야 된다. 완전 실패다. 

 

두 번째 시도(효율성 테스트 실패)

let answer;
    for(let i=0;i<participant.length;i++){
        for(let j=0; j<completion.length;j++){
            if(participant[i]==completion[j]){
                participant.splice(i,1);
                completion.splice(j,1);
                
                if(i==0) i--;
                break;
            }
        }
    }
    answer=participant[0];

배열의 크기를 줄여야 된다는 생각에 괜히  splice를 찾아봤다. 그런데 백억 번 돌리는 건 똑같다;; 

 

세 번째 시도(성공) 

let answer;
    participant.sort(); 
    completion.sort();
    completion[completion.length]=undefined;

    for(let i=0; i<participant.length;i++){
        if(participant[i]!==completion[i]){
          answer=participant[i]; 
          break;
        }
    }

 

그러면 두 배열 다 정렬하고 앞에서부터 비교하면서 만약에 다른 값이 나오면 그게 완주 못한 사람이니까... 

쉽게 생각하니까 풀렸다.

if(participant[i]!==completion[i]) 이렇게 비교를 하는데 

completion의 길이가 participant 보다 하나 작으니까, 마지막에는 completion[i]가 없으니까.  에러가 날까봐 

뒤에 하나 추가해줬다. 그런데 다른 사람들 풀이 보니까 이건 안 해줘도 되나 보다.

 

다른 사람 풀이 & 소감

=>  이런 거 써서 코드 딱 한 줄로 푼 것도 있던데. 짧은 거는 놀랐는데, 내가 읽기는 힘든 코드라 그냥 넘어갔다.

짧으면 당연히 좋지만, 그건 뭔가 마음에 안 드는 구조다. 특히 함수 안에 =>  이거 쓰는 게 너무 마음에 안 든다. 

나는 저 짧은 코드의 가독성에 스트레스받지만. 다른 사람들은 그 코드에 환호했다.  나도 빨리 짧은 코드를 쉽게 이해하고 싶다. 

 

아직까지는 쉬워서 스트레스받지도 않고 쉽게 즐길 수 있다. 빨리 스트레스받는 어려운 문제를 풀고 싶다.   


오늘의 함수 

두 번째 시도에서 splice()를 사용했는데 사실 그전에 계속 slice를 쓰면서 왜 배열이 삭제가 안 되는 건지 헤맸다. 

 

Array.prototype.slice()  

어떤 배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합.

원본 배열은 바뀌지 않는다. -> 얕은 복사

arr.slice([begin[, end]]) 

 

begin은 시작 부분 인덱스를 가리킨다. 

없거나 배열의 길이보다 크다면 배열 전체를 복사한다. 

 

end는 종료 부분 인덱스 +1이다. 

예를 들어 

arr.slice(1,100)는 1번 인덱스부터 100전까지.  그러니까 1부터 99까지의 인덱스 값을 복사한다. 

 

begin과 end를 사용할 때 음수를 사용하여 끝에서부터 몇 번째에 있는 인덱스를 지정할 수 있다.

 

예를 들어 slice(-2) 는 배열에서 마지막 두 개의 엘리먼트를 추출한다.

slice(2,-1) 는 세 번째부터 끝에서 두 번째 요소까지 추출한다.

 

Array.prototype.splice()

 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경한다.

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

 

MDN의 설명이 정말 자세하다. 

 

start 변경의 시작 지점을 정한다. 

deleteCount 시작 지점에서부터 시작해서 몇 개를 삭제할지 정한다. 

item1, item2, ... 시작 지점에서 새로 추가할 내용 

 


  

728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함