본문 바로가기
코딩테스트/프로그래머스

프로그래머스 | Python | 단순구현, Hash | 신고 결과 받기 (Lv.1)

by RuntimeSimple 2025. 2. 13.

https://school.programmers.co.kr/learn/courses/30/lessons/92334

 

def solution(id_list, report, k):
    # 1. 중복 신고 제거
    report_set = set(report)

    # 2. 신고당한 횟수를 저장하는 딕셔너리
    report_count = {user: 0 for user in id_list}

    # 3. 신고 내역을 저장하는 딕셔너리 (set 사용으로 중복 방지)
    report_history = {user: set() for user in id_list}

    # 4. 신고 내역 처리
    for entry in report_set:
        reporter, reported = entry.split()
        report_count[reported] += 1
        report_history[reporter].add(reported)  # 중복 신고 방지

    # 5. k번 이상 신고당한 유저 목록 생성
    banned_user = {user for user, count in report_count.items() if count >= k}

    # 6. 각 유저가 받을 메일 개수 계산 (set 교집합 사용으로 최적화)
    result = [len(report_history[user] & banned_user) for user in id_list]

    return result

1. 문제 분석

  • 각 사용자는 특정 사용자를 신고할 수 있음.
  • 동일한 사용자를 여러 번 신고해도 한 번만 신고한 것으로 처리됨.
  • 특정 사용자가 K번 이상 신고되면 이용 정지됨.
  • 신고한 사용자가 정지된 경우, 신고한 사람에게 메일을 발송해야 함.
  • 최종적으로 각 사용자가 받은 메일 개수를 출력하면 됨.

2. 핵심 개념 및 알고리즘

  • 해시맵(Dictionary)을 활용하여 신고 내역을 중복 없이 저장.
  • 각 사용자의 신고당한 횟수를 저장.
  • 신고한 사용자가 정지되었을 때, 신고한 사람에게 메일을 보냄.

코드에서 report_history[user] & banned_user의 의미

result = [len(report_history[user] & banned_user) for user in id_list]

report_history[user]

  • 특정 유저가 신고한 유저들의 집합(set)입니다.

banned_user

  • 정지된 유저들의 집합(set)입니다.
  • banned_user: {} 중괄호 안에 for 구문이 있으면 set 컴프리헨션입니다.

report_history[user] & banned_user

  • 특정 유저(user)가 신고한 유저들 중에서 실제로 정지된 유저들의 집합을 반환합니다.

len(report_history[user] & banned_user)

  • 해당 유저가 신고한 유저들 중에서 정지된 유저가 몇 명인지를 계산합니다.

예시

result = [len(report_history[user] & banned_user) for user in id_list]
# 각 유저가 신고한 유저들 중에서 정지된 유저 수를 계산
# muzi -> {"frodo", "neo"} & {"frodo", "neo"}  => {"frodo", "neo"} (2명)
# frodo -> {"neo"} & {"frodo", "neo"}  => {"neo"} (1명)
# apeach -> {"frodo", "muzi"} & {"frodo", "neo"} => {"frodo"} (1명)
# neo -> set() & {"frodo", "neo"} => set() (0명)

print(result)  # [2, 1, 1, 0]

예제 흐름 분석

id_list = ["muzi", "frodo", "apeach", "neo"]
report = ["muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi"]
k = 2

코드 흐름

1. 중복 신고 제거

  • 중복 신고가 있는 경우 1회로 처리
  • set(report) 사용하여 중복 제거
report_set = {
    "muzi frodo",
    "apeach frodo",
    "frodo neo",
    "muzi neo",
    "apeach muzi"
}

2. 신고당한 횟수를 저장하는 딕셔너리

  • 모든 유저를 0으로 초기화
report_count = {
    "muzi": 0,
    "frodo": 0,
    "apeach": 0,
    "neo": 0
}

3. 신고 내역 저장 (set 사용)

  • 각 유저가 신고한 목록 저장
  • set을 사용하여 중복 신고 방지
report_history = {
    "muzi": {"frodo", "neo"},
    "frodo": {"neo"},
    "apeach": {"muzi", "frodo"},
    "neo": set()
}

4. 신고 내역 처리 (report_count 갱신)

  • 누가 몇 번 신고당했는지 카운트
report_count = {
    "muzi": 1,  # apeach가 신고
    "frodo": 2,  # muzi, apeach가 신고
    "apeach": 0,
    "neo": 2  # muzi, frodo가 신고
}

5. k번 이상 신고당한 유저 목록 생성

  • k = 2 이상 신고당한 유저: "frodo", "neo"
banned_user = {"frodo", "neo"}

6. 각 유저가 받을 메일 개수 계산

  • report_history[user]과 banned_user의 교집합 개수 계산
result = [
    len({"frodo", "neo"} & {"frodo", "neo"}),  # muzi → 2회
    len({"neo"} & {"frodo", "neo"}),  # frodo → 1회
    len({"muzi", "frodo"} & {"frodo", "neo"}),  # apeach → 1회
    len(set() & {"frodo", "neo"})  # neo → 0회
]

→ result = [2, 1, 1, 0]