프로그래머스/lv1

프로그래머스 : 해시 > 완주하지 못한 선수(lv1) c++

TIN9 2023. 4. 25.
반응형

프로그래머스 링크

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제 설명

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

마라톤에 참여한 선수들의 이름이 담긴 배열 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"

코드 풀이

우선 자료구조 선택을 탐색이 빠른 자료구조를 떠올렸다

하지만 위의 문제에서 동명이인이 있을 수 있다고 하여

unordered_multimap을 사용하였다.

 

  1. 경기에 참여한 선수 모두를 map에 넣는다
  2. 경기를 완주한 선수들을 map에서 탐색후 제거
  3. 단 한 명의 선수를 제외하고 모든 선수가 마라톤을 완주하였다고 나와있기 때문에 map에 남은 선수는
    단 한 사람일 것이다. 그러므로 map.begin()->first가 정답이 된다

이 문제를 풀면서 좀 꺼렸던부분은 map을 제거하는 부분이였다.

 

unordered_map의 경우 해쉬기반 자료구조이기 때문인데

해시 테이블을 사용하여 요소를 저장하고 요소를 제거하려면 테이블에서 해당 위치를 찾아야 하기 때문이고

또, unordered_multimap에서 요소를 제거하면 Rehashing이 발생할 수 있는데 이러한 부분은 비용이 큰 작업이라는것을 알고있기 때문이다.

Rehashing은 해시 테이블의 크기를 조정하고 새 테이블에 모든 요소를 다시 넣는 과정이기때문에 자주 수행하면 성능 저하가 발생할 수 있다고하니 꺼림찍했지만 그래도 선수가 몇백만 몇천만이 아니기도 하고 이 방법이 나쁜 방법은 아닌거 같다고 생각이 들어서 아래와 같은 코드로 구현

코드

#include <string>
#include <vector>
#include <unordered_map>

using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    string answer = "";

    // 중복가능한 키값을 저장할 수 있는 unordered_multimap변수 지정
    unordered_multimap<string, bool> mapName;

    size_t Size = participant.size();

    // 참여한 선수를 전부 map에 저장
    for(size_t i = 0; i < Size; ++i)
    {
        mapName.insert(make_pair(participant[i], true));
    }

    size_t CompletionSize = completion.size();

    // 완주한 선수들을 전부 제거
    for(size_t i = 0; i < CompletionSize; ++i)
    {
        auto iter = mapName.find(completion[i]);

        if(iter != mapName.end())
        {
            mapName.erase(iter);
        }
    }

    // 제거하고 남은 선수는 단 한명뿐이기 때문에 begin의 키값을 얻어온다.
    answer = mapName.begin()->first;

    return answer;
}

정확성

반응형

댓글