이 문제는 코드보다 먼저 문제를 단계로 끊어서 보는 게 핵심이다.
처음 보면 그렇게 어려워 보이지 않는다.
누가 누구를 신고했고, 일정 횟수 이상 신고당하면 정지되고, 그 사람을 신고한 사람에게 메일이 간다.
말로 하면 단순한데, 막상 구현 들어가면 자꾸 꼬인다.
이유는 하나다.
이 문제는 한 번에 처리하려고 하면 안 되고,
반드시 아래 순서로 나눠서 봐야 한다.
- 중복 신고 제거
- 신고 관계 저장
- 신고당한 횟수 카운트
- 정지 대상 판별
- 메일 수 계산
즉, 이 문제는 딕셔너리 문법 문제가 아니라
구현 문제를 구조화하는 문제에 더 가깝다.
🔗 문제 링크
프로그래머스 92334 - 신고 결과 받기
https://school.programmers.co.kr/learn/courses/30/lessons/92334
문제 정리
입력은 이렇게 들어온다.
- id_list : 전체 유저 목록
- report : "신고자 피신고자" 형태의 문자열 목록
- k : 정지 기준 신고 횟수
출력은
각 유저가 최종적으로 받게 되는 메일 개수다.
문제에서 중요한 조건은 이거다.
- 같은 사람이 같은 사람을 여러 번 신고해도 1번만 인정
- 어떤 유저가 k번 이상 신고당하면 정지
- 정지된 유저를 신고한 사람에게만 메일 발송
즉, 이 문제는 단순히 “누가 많이 신고당했나”만 보는 문제가 아니다.
신고 관계와 카운트를 같이 봐야 한다.
✅ 핵심 아이디어
이 문제는 아래 4단계로 나누면 된다.
- report를 set으로 바꿔서 중복 신고 제거
- 신고 관계 저장
- 피신고 횟수 카운트
- 각 유저가 신고한 대상 중 정지된 사람이 몇 명인지 계산
이 흐름만 잡히면 구현은 생각보다 길지 않다.
정답
def solution(id_list, report, k):
report = set(report)
reported_by = {user: [] for user in id_list}
reported_count = {user: 0 for user in id_list}
for r in report:
reporter, target = r.split()
reported_by[reporter].append(target)
reported_count[target] += 1
answer = []
for user in id_list:
mail_count = 0
for target in reported_by[user]:
if reported_count[target] >= k:
mail_count += 1
answer.append(mail_count)
return answer
생각해야 하는 부분
이 문제는 구현 디테일보다
각 자료구조에 뭘 담을지를 먼저 정해야 한다.
1. 먼저 중복 신고를 제거해야 한다
이 문제에서 제일 먼저 해야 할 일은 이거다.
report = set(report)
문제 조건상
같은 사람이 같은 사람을 여러 번 신고해도 1번만 인정된다.
즉, 나중에 카운팅하기 전에
이 중복부터 제거해야 한다.
이걸 뒤로 미루면
신고 횟수 자체가 잘못 올라가서 전체 결과가 틀어진다.
2. 신고 관계 저장과 피신고 횟수 카운트는 분리해서 봐야 한다
이 문제는 딕셔너리가 두 종류 필요하다.
reported_by = {user: [] for user in id_list}
reported_count = {user: 0 for user in id_list}
각 역할은 이렇다.
- reported_by[user]
- 이 유저가 누구를 신고했는지 저장
- reported_count[user]
- 이 유저가 몇 번 신고당했는지 저장
즉, 하나는 관계 저장, 하나는 횟수 카운트다.
이걸 한 구조에 다 몰아넣으려고 하면 바로 헷갈린다.
3. split()으로 신고자와 피신고자를 나눈다
report 안에는 이런 문자열이 들어 있다.
"muzi frodo"
이걸 쪼개면
- 신고자 = muzi
- 피신고자 = frodo
가 된다.
reporter, target = r.split()
이 문제에서 split()은 그냥 문자열 처리 문법이 아니라,신고 관계를 분해하는 핵심 단계다.
4. 마지막엔 “내가 신고한 사람 중 정지된 사람 수”를 세면 된다
앞 단계까지 끝나면
각 유저가 신고한 목록과, 각 유저가 몇 번 신고당했는지가 정리돼 있다.
그다음은 단순하다.
for user in id_list:
mail_count = 0
for target in reported_by[user]:
if reported_count[target] >= k:
mail_count += 1
answer.append(mail_count)
즉,
내가 신고한 사람들 중에서
최종적으로 정지된 사람이 몇 명인지 세면 그게 메일 개수다.
예외처리 / 주의할 점
⚠️ 1. 중복 신고 제거를 빼먹으면 바로 틀린다
이 문제에서 제일 먼저 챙겨야 하는 조건이 이거다.
같은 사람이 같은 사람을 여러 번 신고해도 1번만 인정된다.
그래서 무조건 먼저
report = set(report)
이걸 해줘야 한다.
이걸 안 하면 reported_count가 실제보다 크게 잡힌다.
⚠️ 2. 메일은 “정지된 사람을 신고한 사람”에게만 간다
처음 보면
“신고당한 횟수 세고, 많이 당한 사람 찾고, 끝”처럼 보일 수 있다.
근데 문제는 거기서 안 끝난다.
출력은 정지된 사람 목록이 아니라
각 유저가 몇 개의 메일을 받는지다.
즉 마지막 단계까지 꼭 가야 한다.
⚠️ 3. id_list 순서대로 답을 만들어야 한다
출력은 딕셔너리 순서가 아니라
문제에서 준 id_list 순서 기준이다.
그래서 마지막도 이렇게 가야 한다.
for user in id_list:
...
answer.append(mail_count)
이 순서를 놓치면
값은 맞아도 제출 형식이 틀릴 수 있다.
⚠️ 4. 이 문제는 자료구조 역할 분리가 중요하다
이 문제는 딕셔너리 하나로 다 밀어붙이려고 하면 어렵다.
- 신고 관계
- 피신고 횟수
- 메일 계산
이 역할을 나눠서 봐야 한다.
즉, 코드를 줄이는 것보다
구조를 분리해서 보는 게 먼저다.
내 시행착오
이 문제는 내가 처음에 꽤 오래 붙잡았던 문제다.
이유는 코드 문법보다 문제 구조가 한 번에 안 보였기 때문이다.
1. 한 번에 처리하려고 했다
처음엔 대충 이런 식으로 생각했다.
- report 나누고
- 누가 누구 신고했는지 넣고
- 정지자 찾고
- 메일 보내고
말로 하면 쉬운데,
이걸 한 흐름으로 바로 코드로 옮기려니까 자료형이 계속 꼬였다.
결국 이 문제는
한 번에 처리하려고 하면 안 되고,
반드시 중간 구조를 먼저 만든다고 생각해야 했다.
2. 자료구조 역할을 명확히 못 나눴다
처음에는 딕셔너리 하나에 다 넣으려고 했는데,
그러면
- 누가 누구를 신고했는지
- 몇 번 신고당했는지
이 둘이 섞여서 헷갈렸다.
이 문제는 결국 딕셔너리를 2개로 나누고 나서야 정리됐다.
- 신고 관계용
- 카운트용
이렇게.
3. 출력이 “정지자”가 아니라 “메일 수”라는 걸 중간에 놓쳤다
이 문제는 정지 대상 찾는 걸로 끝나는 문제가 아니다.
마지막 출력은
각 유저가 받는 메일 수다.
즉, 정지 대상 판별은 중간 단계일 뿐이고
진짜 마지막은 메일 개수 계산이다.
이걸 중간에 놓치면 문제를 다 푼 것 같아도 끝까지 못 간다.
한 줄 정리
이 문제는 딕셔너리 문법 문제라기보다,
신고 관계 / 카운트 / 결과 계산을 단계별로 구조화해서 보는 구현 문제다.
'Coding Test > 문제풀이' 카테고리의 다른 글
| 프로그래머스 완주하지 못한 선수 | set 대신 dictionary를 써야 하는 이유 (0) | 2026.04.23 |
|---|---|
| 프로그래머스 파일명 정렬 | 정규식으로 HEAD, NUMBER, TAIL 나누는 방법 (0) | 2026.04.22 |
| 얼음 얼려 먹기 문제 정리 | DFS로 연결 요소 개수 세는 방법 (0) | 2026.04.21 |
| 백준 2178 미로 탐색 | 좌표형 BFS 구현과 최단거리 풀이 (0) | 2026.04.17 |
| 백준 18352 특정 거리의 도시 찾기 | BFS와 distance 배열 풀이 (0) | 2026.04.15 |
