92334. 신고 결과 받기
프로그래머스 92334번 풀이
이 글은 Obsidian에서 마이그레이션되었으며, 그 과정에서 AI의 도움을 받았습니다. 오류나 누락된 내용이 있다면 댓글로 알려주세요!
문제
코딩테스트 연습 - 신고 결과 받기 | 프로그래머스 스쿨
풀이
아이디어
프로그래머스 형식의 문제를 너무 안푼 것 같아서 도전해봤는데… 문제 자체는 그렇게 어렵진 않았지만 입력 형식이 헷갈려서 죽는 줄 알았다ㅋㅋ 가끔은 프로그래머스 문제도 좀 풀어야겠다..
입력되는 정보는 유저의 ID (ID는 string 형식)가 담긴 id_list, "신고한 사람 ID" "신고당한 사람 ID" 형식의 문자열 배열 report, 그리고 정지 기준이 되는 신고 횟수 k이다. 그리고 return 해야 할 vector answer는 id_list의 순서대로 그 유저가 받는 처리 결과 메일의 개수를 저장해야 한다.
(1) 해야 할 일 첫번째는 당연히 answer 배열을 0으로 초기화 하는 것.
vector<int> answer(id_list.size(), 0);이렇게 초기화 해 주면 된다.
(2) 다음에는 "신고한 사람 ID" "신고당한 사람 ID" 형식으로 입력되는 정보를 파싱하기 위해서 get_name 함수를 만들어줬다. 형식이 딱 정해져 있기 때문에 가운데 공백을 기준으로 앞쪽과 뒷쪽으로 나누어서 pair 형태로 반환해주었다.
(3) 그리고 유저의 ID를 key로, 해당 유저가 신고한 ID의 목록의 set을 value로 갖는 map singo_list, 유저 ID를 key로, 해당 유저가 신고당한 횟수를 value로 하는 map singodang_cnt를 선언해주었다. 네이밍 센스가 참 어디 선보이기 너무 민망한 수준이다…
singo_list의 value가 되는 신고한 ID의 목록을 set으로 설정한 이유는 중복 신고를 허용하지 않기 때문이다! 사실 신고 목록을 저장하는 반복문에서 중복 신고의 경우에는 singodang_cnt의 내용을 변경하면 안되기 때문에 중복 신고의 경우를 걸러주는 부분이 있어서 내가 짠 코드 내에서는 set으로 굳이 안해도 되었을 것 같긴 하다. ㅎㅎ
(4) 다음에는 신고 목록을 저장해준다! 앞서 말했듯이 report 배열을 돌면서 singo_list["신고자 ID"] 에 "신고당한 ID"가 있는지 확인한 후에, 없다면 singo_list["신고자 ID"]에 추가하고 singodang_cnt["신고당한 ID"]를 증가시켜준다.
(5) 마지막으로는 id_list 내의 ID에 해당하는 singo_list를 또 돌면서 singodang_cnt의 값이 k보다 크거나 같은 경우가 있는지 확인하고, 있다면 그 신고자 ID에 해당하는 인덱스 (코드를 보면 알겠지만, id_list를 순차적으로 탐색하고 있기 때문에 굳이 ID ↔️ index로 변환하는 작업 없이 작업하고있는 인덱스 i를 그대로 써줘도 괜찮았다.)의 answer 값을 증가시켜줬다.
끝!
코드
#include <string>
#include <vector>
#include <set>
#include <map>
#include <utility>
using namespace std;
pair<string, string> get_name(string report)
{
pair<string, string> ret;
int idx = 0;
while (report[idx] != ' ')
idx++;
ret.first = report.substr(0, idx);
idx++;
ret.second = report.substr(idx, report.length() - idx);
return (ret);
}
vector<int> solution(vector<string> id_list, vector<string> report, int k) {
vector<int> answer(id_list.size(), 0);
map<string, set<string> > singo_list; // (유저 ID, 해당 유저가 신고한 ID의 목록)
map<string, int> singodang_cnt; // (유저 ID, 해당 유저가 신고당한 횟수)
pair<string, string> name; // first: 이용자 ID, second: 신고한 ID
// 신고당한 횟수 초기화
for(int i = 0; i < id_list.size(); i++)
singodang_cnt[id_list[i]] = 0;
// 신고 목록 저장
for(int i = 0; i < report.size(); i++)
{
name = get_name(report[i]);
// 앞선 신고 이력이 없을 경우 추가하고 신고 횟수를 늘린다.
if (singo_list[name.first].find(name.second) == singo_list[name.first].end())
{
singo_list[name.first].insert(name.second);
singodang_cnt[name.second]++;
}
}
// id list를 돌면서 자신이 신고한 ID 중 신고 횟수가 k가 넘는 경우에 answer의 값을 증가시킨다.
for(int i = 0; i < id_list.size(); i++)
{
for(auto iter = singo_list[id_list[i]].begin(); iter != singo_list[id_list[i]].end(); iter++)
{
if (singodang_cnt[*iter] >= k)
answer[i]++;
}
}
return answer;
}