코딩테스트 공부
[프로그래머스] 신고 결과 받기 (C++)
kkyoug
2025. 4. 12. 21:20
해당 문제는 해시를 활용하여 k번 이상 신고된 사람을 누가 신고했는지 체크하는 방법이다. 기본적으로 map, set에 관한 지식이 많고 범위기반 반복문을 잘 활용한다면 문제는 쉽게 해결되었다.
📌 문제 설명
시스템 동작 조건
- 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
- 신고 횟수에 제한은 없습니다.
- 동일한 유저를 여러 번 신고해도 1회로 처리됩니다.
- k번 이상 신고된 유저는 게시판 이용 정지됩니다.
- 유저가 신고한 내용은 취합 후 일괄 처리되며,
- 정지된 유저를 신고한 사람은 메일을 받게 됩니다.
🧾 예시
입력 예시:
id_list = ["muzi", "frodo", "apeach", "neo"];
report = ["muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi"];
k = 2;
📊 신고 내역 분석
유저 ID 신고당한 횟수
muzi | 1 |
frodo | 2 ✅ |
apeach | 0 |
neo | 2 ✅ |
정지된 유저: frodo, neo
📩 메일 수신 결과
유저 ID 신고한 ID 정지된 ID 메일 수신 횟수
muzi | ["frodo", "neo"] | ["frodo", "neo"] | 2 |
frodo | ["neo"] | ["neo"] | 1 |
apeach | ["muzi", "frodo"] | ["frodo"] | 1 |
neo | 없음 | 없음 | 0 |
✅ 목표
각 유저가 정지된 유저를 신고했는지 확인해,
각 유저가 받은 메일 수를 반환하자!
🧑💻 C++ 코드
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <unordered_set>
#include <map>
using namespace std;
vector<int> solution(vector<string> id_list, vector<string> report, int k) {
vector<int> answer;
unordered_map<string, unordered_set<string>> check_report;
unordered_map<string, int>result;
// 신고 수 체크
for(int i = 0; i<report.size(); i++){
stringstream ss(report[i]); // muzi frodo
string user_id, reported_id;
ss>>user_id>>reported_id;
// 중복 제거
check_report[reported_id].insert(user_id); // frodo - {muzi, apeach}
}
for(auto & [reported_id, user_id] : check_report){ //frodo - {muzi, apeach}
if(user_id.size() >=k){ // k명 이상에게 신고를 당했는지
for(const auto & uid : user_id){ // 신고당한 횟수 기록
result[uid]++;
}
}
}
for(string &id : id_list){
answer.push_back(result[id]);
}
return answer;
}
✨ 코드 진행 과정 상세 설명
이 코드는 불량 이용자 신고 시스템을 구현한 것으로, 신고가 일정 횟수 이상 누적되면 해당 유저를 정지시키고, 정지된 유저를 신고한 사람들에게 처리 결과 메일을 보내는 로직을 담고 있습니다.
1. 변수 준비
unordered_map<string, unordered_set<string>> check_report;
unordered_map<string, int> result;
- check_report는 누가 누구를 신고했는지 기록하는 자료구조입니다.
→ 중복 신고 방지를 위해 unordered_set 사용
→ 예: "frodo" → { "muzi", "apeach" } - result는 각 유저가 받은 결과 메일의 수를 저장합니다.
2. 신고 내역 정리 (중복 제거 포함)
for(int i = 0; i < report.size(); i++) {
stringstream ss(report[i]);
string user_id, reported_id;
ss >> user_id >> reported_id;
check_report[reported_id].insert(user_id);
}
- report는 "신고자 신고당한사람" 형식의 문자열입니다.
- stringstream으로 나눠서 신고자(user_id)와 피신고자(reported_id)를 분리합니다.
- 동일한 사람이 동일 유저를 여러 번 신고해도 1번만 인정되도록 insert로 저장합니다.(set 사용)
3. 정지 대상 확인 + 메일 받을 사람 카운트
for(auto & [reported_id, user_id_set] : check_report) {
if(user_id_set.size() >= k) {
for(const auto & uid : user_id_set) {
result[uid]++;
}
}
}
- check_report를 순회하며, 신고자가 k명 이상이면 정지 대상입니다.
- 해당 피신고자를 신고한 모든 사람(uid)은 메일을 받게 되므로 result[uid]++ 해줍니다.
4. 유저 순서에 맞게 정답 배열 생성
for(string &id : id_list){
answer.push_back(result[id]);
}
- 문제에서는 id_list에 있는 순서대로 결과 메일 수를 반환하라고 했기 때문에,
→ result에 없는 유저는 자동으로 0이 들어갑니다 (기본값). - 최종적으로 answer에 메일 받은 횟수를 담아 리턴합니다.
💡 핵심 개념 요약
- unordered_map + unordered_set을 사용해 중복 제거 및 신고 내역 기록.
- stringstream 으로 문자열에서 유저 ID 추출.
- map 순회 (for (auto& [key, val] : map)) 를 통해 깔끔하게 처리.