완주하지 못한 선수
수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.
마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.
제한사항- 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
- completion의 길이는 participant의 길이보다 1 작습니다.
- 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
- 참가자 중에는 동명이인이 있을 수 있습니다.
["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"는 참여자 명단에는 두 명이 있지만, 완주자 명단에는 한 명밖에 없기 때문에 한명은 완주하지 못했습니다.
<code>
function solution(participant, completion) {
participant.sort();
completion.sort();
console.log(participant);
console.log(completion);
for (let i = 0; i < participant.length; i++) {
if (participant[i] !== completion[i]) {
console.log(participant[i]);
return participant[i];
}
}
}
solution(["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]);
이 방법의 핵심은 sort이다.
sort로 정렬 한 후 다른 값을 반환시켜주면 되는것!
sort 힌트를 얻고 정말 쉽게 풀었지만 ,
이전에 해쉬함수를 이용해 풀려고 하니 애를 많이 먹었다.
function solution(participant, completion) {
/*
for(let i in participant) {
if(completion.includes(participant[i]) == false) return participant[i];
completion.splice(completion.indexOf(participant[i]), 1);
}
*/
participant.sort();
completion.sort();
for(let i in participant) {
if(participant[i] !== completion[i]) return participant[i];
}
}
for문을 이런식으로 간단하게 써도 된다!
이때 for in 과 for of의 차이를 알아보자
for ...in - 객체의 속성들을 반복하여 작업
var obj = {
a: 1,
b: 2,
c: 3
};
for (var prop in obj) {
console.log(prop, obj[prop]); // a 1, b 2, c 3
}
for ...of - 반복가능한 객체 (Array, Map, Set, String, TypedArray, arguments 객체 등을 포함)에 대해서 반복
var iterable = [10, 20, 30];
for (var value of iterable) {
console.log(value); // 10, 20, 30
}
Map() 해쉬함수를 이용한 풀이 방법이다.
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';
}
solution(["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]);
코딩을 봐도 도저히 이해가 안가서 애를 먹었다.
map.set(a, (map.get(a) || 0) + 1); map.set(b, (map.get(b) || 0) - 1); map.get(a)||0
이부분이 이해가 안갔다..
프로그래머스에서 설명을 해주셔서 이 부분을 가져왔다!!
map.set 메소드로 map에 새로운 객체를 추가할수있습니다 map.set(key, value)형태로 객체를 추가하게 되는데 a,즉 participant의 첫번째 요소부터 추가를 하게되는것이죠 처음 추가를 하게 되면 key값으로 a가 전달이 되고 value값으로 map.get(a) || 0 + 1 이 전달이 되는건데 a가 처음 추가되는 상황이므로 map.get(a)가 false이므로 0이 출력값이 되고 1을 더하니 결과적으로 key에 a, value에 1이 map에 저장됩니다
근데 만약 map에 a가 이미 추가되어있는 상황이라면(동명이인) map에 key가 a value가 1인 객체가 있는 상황입니다. 그렇게 되면 map.get(a)가 true가 되므로 map.get(a) || 0)가 map.get(a)가 나오게 되고(즉 1이 나오게 됨) +1을 하면 a의 value값으로 2가 전달이 되는것이죠 이제 b를 살펴보면 같은 원리로 b가 이미 map에 있다면 (즉 완주자라면)a 1 인 상태에서 -1이 되어 value값이 0이 됩니다 반대로 없는 경우에는(즉 완주를 못함) a에서는 있었으므로 value값이 1이지만 완주를 못해 b에는 없으므로 아무변화가 없어 value값이 1인상태로 남게 됩니다 또한 동명이인의 경우에는 a에서 한번더 1이 더해져 value가 2인상태에서 b에서 1을 뺀다고 해도 값이 1이 남게됩니다 결국 아래 for 문에서 value값이 0이상 즉 1 인 값들(미완주자, 동명이인)이 출력이 되게 되는것이죠
풀이를 읽어도 이해가 안돼서ㅠ0ㅠ 코딩을 돌려보았다.
?? 이게 무슨소리지 ??
머리가 안좋으면 몸이 고생 하기 때문에 직접 그림을 그려보았다.ㅋ
내 글을 보는 사람이 있을 지는 모르겠지만,, 설명해보자면
solution(["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]);
위와 같은 배열이 주어졌다고 가정하고 map에 for문을 돌면서 participant[i] 값 하나와 completion[i] 값 하나를 set를 이용하여 넣어준다. 이때 그냥 넣어주는 것이 아니라 넣어줄때 participant쪽에 있으면 +1 해주고 completion에 있으면 -1을 넣어준다. 근데 중요한 것은 map.get(a)로 가져온 값에다 넣어주는것
즉 내 그림은
participant의 mislav은 처음에 set함수로 넣을때는 없으니까 map.get(a) 는 0 이된다. 0 + 1 => 1
completion의 stanko는 처음에 set함수로 넣을때는 없으니까 map.get(a) 는 0이 된다. 0 -1 => -1
participant의 stanko은 이미 있으니까 map.get(a) 값은 이전에 계산한 -1이된다. -1 + 1 =0
completion의 ana는 처음에 set함수로 넣을때는 없으니까 map.get(a) 는 0이 된다. 0 -1 => -1
이런식으로 풀면 된다..
이해하고 결과 값을 다시 보니 이해가 쏙쏙!