- 자격증
- cloud_computing
- 2023_1st_Semester
- codingTest
- Android
- SingleProject
- Unix_System
- Image_classification
- Linux
- Operating_System
- Baekjoon
- study
- 티스토리챌린지
- c++
- C
- Kubernetes
- Database_Design
- Artificial_Intelligence
- app
- tensorflow
- 오블완
- datastructure
- Java
- Personal_Study
- Algorithm
- programmers
- Univ._Study
- pytorch
- 리눅스마스터2급
- Python
코딩 기록 저장소
[프로그래머스/C++] 신고 결과 받기 본문
문제 정보
제목 : 신고 결과 받기
난이도 : Lv.1
사용 언어 : C++
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/92334
문제 설명
신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.
- 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
- 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
- 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
- k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
- 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.
다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.
유저 ID | 유저가 신고한 ID | 설명 |
"muzi" | "frodo" | "muzi"가 "frodo"를 신고했습니다. |
"apeach" | "frodo" | "apeach"가 "frodo"를 신고했습니다. |
"frodo" | "neo" | "frodo"가 "neo"를 신고했습니다. |
"muzi" | "neo" | "muzi"가 "neo"를 신고했습니다. |
"apeach" | "muzi" | "apeach"가 "muzi"를 신고했습니다. |
각 유저별로 신고당한 횟수는 다음과 같습니다.
유저 ID | 신고당한 횟수 |
"muzi" | 1 |
"frodo" | 2 |
"apeach" | 0 |
"neo" | 2 |
위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.
유저 ID | 유저가 신고한 ID | 정지된 ID |
"muzi" | ["frodo", "neo"] | ["frodo", "neo"] |
"frodo" | ["neo"] | ["neo"] |
"apeach" | ["muzi", "frodo"] | ["frodo"] |
"neo" | 없음 | 없음 |
따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.
이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한 사항
- 2 ≤ id_list의 길이 ≤ 1,000
- 1 ≤ id_list의 원소 길이 ≤ 10
- id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
- id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
- 1 ≤ report의 길이 ≤ 200,000
- 3 ≤ report의 원소 길이 ≤ 21
- report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
- 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
- id는 알파벳 소문자로만 이루어져 있습니다.
- 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
- 자기 자신을 신고하는 경우는 없습니다.
- 1 ≤ k ≤ 200, k는 자연수입니다.
- return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.
입출력 예
id_list | report | k | result |
["muzi", "frodo", "apeach", "neo"] | ["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"] | 2 | [2,1,1,0] |
["con", "ryan"] | ["ryan con", "ryan con", "ryan con", "ryan con"] | 3 | [0,0] |
입출력 예 설명
입출력 예 #1
문제의 예시와 같습니다.
입출력 예 #2
"ryan"이 "con"을 4번 신고했으나, 주어진 조건에 따라 한 유저가 같은 유저를 여러 번 신고한 경우는 신고 횟수 1회로 처리합니다. 따라서 "con"은 1회 신고당했습니다. 3번 이상 신고당한 이용자는 없으며, "con"과 "ryan"은 결과 메일을 받지 않습니다. 따라서 [0, 0]을 return 합니다.
제한시간 안내
- 정확성 테스트 : 10초
나의 풀이
이전의 시도
처음엔 맵을 쓰지않고 pair클래스를 이용해서 report_list에 유저의 ID와 신고당한 횟수(0)를 저장합니다. 반복문을 이용하여 set에 report를 넣어 중복을 제거하고, set을 하나씩 순회하면서 stringstream을 이용하여 문자열을 나누어 만약 신고 당한 아이디와 report_list[j]에 들어있는 유저와 같다면 그에 해당하는 신고당한 횟수를 추가하였습니다. 반복문이 끝나면 report_list의 길이만큼 반복하며 신고당한 횟수가 k 이상일때 user_list라는 set에 추가했습니다. 그래서 신고 당한 횟수 계산, 정지 당한 유저 ID 알아내는것까진 성공했지만 이후 과정에서 큰 어려움을 겪었습니다.
#include <string>
#include <vector>
#include <iostream>
#include <set>
#include <sstream>
using namespace std;
vector<int> solution(vector<string> id_list, vector<string> report, int k) {
vector<int> answer(id_list.size(),0);
set<string> user_list;
vector<pair<string,int>> report_list;
set<string> s;
string ss,id1,id2;
for(int i =0 ; i < id_list.size();i++)
report_list.push_back(pair<string,int>(id_list[i],0));
for(int i = 0; i < report.size(); i ++)
s.insert(report[i]);
for (auto iter = s.begin(); iter != s.end(); iter++) {
ss = *iter;
stringstream s2(ss);
s2 >> id1 >> id2;
for(int j = 0; j < report_list.size(); j ++ )
{
if (id2 == report_list[j].first)
{
report_list[j].second += 1;
}
if (report_list[j].second >= k)
user_list.insert(report_list[j].first);
}
}
for(int i = 0 ; i < report_list.size();i++)
{
cout<< report_list[i].first << " " << report_list[i].second <<endl;
}
cout<<"정지 당한 유저 ID" <<endl;
for (auto i : user_list)
cout << i <<endl;
return answer;
}
이 방법으로는 도저히 안될것 같아 다른 방법을 찾아보던 중 map을 이용하면 해결할 수 있다는 것을 알았습니다.
user_index 맵에 유저의 ID와 인덱스를 미리 저장해둡니다. report의 길이만큼 반복하며 stringstream을 이용하여 문자열을 나누어 report_list에 유저를 신고한 사람의 ID를 추가합니다.
이후 report_list를 순회하며 신고한 사람의 수가 k이상이라면 그 유저의 인덱스를 알아낸 후 answer[index]에 1을 증가시키는 방식으로 해결할 수 있습니다.
+ 아직 맵은 사용하는게 익숙하지 않았습니다. 맵을 자세히 공부하여 응용할 수 있다면 다양한 문제를 풀 수 있을 것 같습니다.
코드
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>
using namespace std;
vector<int> solution(vector<string> id_list, vector<string> report, int k) {
vector<int> answer(id_list.size(),0);
map<string,int> user_index;
map<string,set<string>> report_list;
string ss,id1,id2,id3;
for(int i =0 ; i < id_list.size();i++)
user_index[id_list[i]] = i; // 멤버 인덱스를 추가함
for (int i =0 ; i < report.size(); i++) {
stringstream ss(report[i]);
ss >> id1 >> id2;
report_list[id2].insert(id1); // 신고 정보를 저장함
}
for (auto i : report_list)
{
if(i.second.size() >= k) // 신고한 횟수가 k 이상이면 실행
{
for (auto index : i.second){
answer[user_index[index]]++;
}
}
}
return answer;
}
'프로그래머스 > Lv.1' 카테고리의 다른 글
[프로그래머스/Python] 추억점수 (1) | 2024.01.10 |
---|---|
[프로그래머스/C++] 개인정보 수집 유효기간 (1) | 2023.01.17 |
[프로그래머스/C++] 성격 유형 검사하기 (0) | 2023.01.17 |
[프로그래머스/C++] 옹알이 (2) (0) | 2023.01.17 |
[프로그래머스/C++] 신규 아이디 추천 (0) | 2023.01.16 |