[프로그래머스] 오픈채팅방 (C++)

교공 알고리즘 스터디 28주차 카카오기출

오픈채팅방 | 문제 바로가기

문제풀이 (2022-03-22 TUE 💻)

⭐ 풀이의 핵심

문자열 split 처리만 잘 해주면 어려울 것 없는 문제였다
(사실 문자열만 마주치면 머리가 하얘지는 나라서.. 문자열 문제랑 친해지려고 고른 문제다)

C++에는 split이라는 함수는 없어서 적절히 조치를 취해줘야 하는데
처음에는 find와 substr을 활용해서 풀었고 코드가 좀 복잡해서
다른 방법을 찾아보니 stringstream 활용하는 방법이 있었다
🚨 사실 substr(pos, count) 가 [pos, count) 범위의 문자열을 반환하는 건 줄로 잘못 알고 있어서 삽질 좀 했다.. [pos, pos+count) 가 맞는 반환 범위다..

그런데 또 특이한 게 (?)
코드 가독성은 몰라도 효율성은 stringstream 보다 find & substr이 더 좋게 나타났다
stringstream은 일단 copy가 한 번 들어가서 그런 것 같다

find & substr 활용 시 결과

stringstream 활용 시 결과

find와 substr, getline 관련 내용은
👉 [C++] 유용한 라이브러리 및 함수 정리 - #include <string> 파트 이 포스트를 참고하면 될듯하다

➕ 참고 stringstream

  • 문자열에서 작동하는 스트림 클래스
  • 주로 주어진 문자열에서 필요한 정보를 자료형에 맞게 파싱해서 빼낼 때 사용
  • #include <sstream> 필요
  • 공백과 줄바꿈 제외 문자열에서 알맞은 자료형을 빼내줌
// example #1
string original = "Hello World!";
stringstream ss(original);
char ch;
while (ss >> ch) {
    cout << ch << " "; // H e l l o W o r l d !
}
string temp;
while (ss >> temp) {
    cout << temp << endl;
}
// example #2
stringstream ss;
ss.str(original);
string str;
while (ss >> str) {
    cout << str << endl;
    // Hello
    // World!
}

🔽 find & substr 활용 코드 (C++)

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

using namespace std;

// Solution #1) find & substr 활용
vector<string> solution(vector<string> record) {
    vector<string> answer;

    int N = record.size();
    vector<string> actionVec;
    vector<string> uidVec;
    unordered_map<string, string> uidMap;

    for (int i=0; i<N; i++) {
        int firstDelim = record[i].find(' ');
        string action = record[i].substr(0, firstDelim);
        actionVec.push_back(action);

        string uid;
        if (action == "Leave") {
            uid = record[i].substr(firstDelim+1);
        }
        else {
            int secondDelim = record[i].find(' ', firstDelim+1);
            uid = record[i].substr(firstDelim+1, secondDelim-firstDelim-1);
            string nickname = record[i].substr(secondDelim+1);
            uidMap[uid] = nickname;
        }
        uidVec.push_back(uid);
    }

    for (int i=0; i<N; i++) {
        string result = "";
        result += uidMap[uidVec[i]];
        if (actionVec[i] == "Enter") { result +=  "님이 들어왔습니다."; }
        else if (actionVec[i] == "Leave") { result += "님이 나갔습니다."; }
        else if (actionVec[i] == "Change") { continue; }
        answer.push_back(result);
    }
    
    return answer;
}

stringstream 활용 코드 (C++)

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

using namespace std;

// Solution #2) stringstream 활용
/*
split 함수도 만들어 보았으나
이 문제는 delimiter가 공백이므로
getline 없이 stringstream 만으로도 풀 수 있다

vector<string> split(string str, char delim) {
    vector<string> answer;
    stringstream ss(str);
    string temp;

    while (getline(ss, temp, delim)) {
        answer.push_back(temp);
    }

    return answer;
}
*/

vector<string> solution(vector<string> record) {
    vector<string> answer;

    vector<pair<string, string>> actionIdVec; // {action, uid}
    unordered_map<string, string> uidNameMap; // {uid: name}
    int N = record.size();
    for (int i=0; i<N; i++) {
        // vector<string> splitVec = split(record[i], ' ');
        vector<string> splitVec;
        stringstream ss(record[i]);
        string temp;
        while (ss >> temp) {
            splitVec.push_back(temp);
        }
        actionIdVec.push_back({splitVec[0], splitVec[1]});           
        if (splitVec[0] != "Leave") {
            uidNameMap[splitVec[1]] = splitVec[2];
        }
    }

    for (int i=0; i<N; i++) {
        string result = "";
        result += uidNameMap[actionIdVec[i].second];
        if (actionIdVec[i].first == "Enter") { result +=  "님이 들어왔습니다."; }
        else if (actionIdVec[i].first == "Leave") { result += "님이 나갔습니다."; }
        else if (actionIdVec[i].first == "Change") { continue; }
        answer.push_back(result);
    }
    
    return answer;
}

좋은 웹페이지 즐겨찾기