프로그래머스 Lv1 신고 결과 받기 java

Dec 4, 2025
프로그래머스 Lv1 신고 결과 받기 java

1. 문제에 대하여 📦

  1. 모든 유저는 다른 유저를 신고할 수 있다.
    1. A 유저가 B 유저에게 여러 번 신고를 하더라도, 신고는 딱 한 번만 카운트 된다.
  1. K 번 이상 신고받은 유저들은 정지가 된다. 이때 이 정지된 유저를 신고한 유저들에게 해당 유저가 정지되었다는 알림 메일을 발송해야 한다.
  1. 각 유저마다 알림 발송된 횟수를 배열로 출력하라.

2. 코드가 나오기까지 🛠️

KEY WORD: HashMap
HashMap이 총 3개 필요했다.
  1. KEY=이름, VALUE=배열 내 인덱스
  1. KEY=이름, VALUE=신고 횟수
  1. KEY=이름, VALUE=KEY에게 신고 넣은 사용자들 HashSet
3번을 Set으로 한 이유는 중복된 신고를 없애기 위해서 이다 .
이후 과정은 report 배열에서 하나씩 꺼내서, 3번을 채운다.
만약 KEY에 대한 신고 넣은 사용자들 LIst의 크기가 커졌으면, 중복되지 않은 신고 요청이 있다는 뜻이므로, 2번의 신고 횟수를 카운트 한다.
2,3번의 계산을 끝낸 이후, 1번을 통해 각 신고자의 신고가 정지로 이어진 횟수를 배열에 대입해서 반환한다.

(1) 시간복잡도 분석 ⏳

유저가 N명이라 할 때, 유저가 다른 모든 유저를 신고하는 경우, report 순회가 O(N * N) 로 커질 수 있다. 내부 계산은 HashMap과 HashSet 계산이므로 O(1)일 것으로 예상된다. 따라서 최악의 시간 복잡도는
O(N) 이다.

3. 코드 🌐

import java.util.*; class Solution { static HashMap<String, Integer> index = new HashMap<>(); // 이름-배열 내 인덱스 static HashMap<String, Integer> cnt = new HashMap<>(); // 각 멤버당 신고당한 횟수 static HashMap<String, HashSet<String>> snitch_list = new HashMap<>(); // 신고당한 놈, 신고 한 사람 리스트 public int[] solution(String[] id_list, String[] report, int k) { // 0. 답이 들어갈 그릇 만들기 for(int i = 0; i < id_list.length; i++){ index.put(id_list[i], i); } int [] answer = new int [id_list.length]; // 신고 당하면 -> 신고 횟수 +1 , 신고자를 신고당한 사람의 스니치 리스트에 넣기 for(int i = 0; i < report.length; i++){ StringTokenizer st = new StringTokenizer(report[i]); String snitch = st.nextToken(); String suspect = st.nextToken(); snitch_list.putIfAbsent(suspect, new HashSet<>()); HashSet<String> list = snitch_list.get(suspect); int prev = list.size(); list.add(snitch); if(prev == list.size()) continue; cnt.compute(suspect, (key,ov) -> (ov==null? 1 : ov+1)); } for(Map.Entry <String, Integer> entry : cnt.entrySet()){ if(entry.getValue() >= k) { HashSet<String> temp = snitch_list.get(entry.getKey()); for(String name : temp) { int idx = index.get(name); answer[idx]++; } } } return answer; } }

4. 트러블 슈팅 or 배운 점📝

  • 루프 돌 때마다 지역 변수를 새로 만드는 것은 effectively final 이다.
for(int i = 0; i <report.length; ; i++){ StringTokenizer st = new StringTokenizer(report[i]); String snitch = st.nextToken(); String suspect = st.nextToken(); snitch_list.compute(suspect, (key,ov) -> { if(ov == null) ov = new HashSet<>(); ov.add(snitch); return ov; }); cnt.compute(suspect, (key,ov) -> (ov == null? 1 : ov+1)); }
위의 코드는 snitch를 루프마다 새로 만들므로 snitcheffectively final 이다.
for(int i = 0; i <report.length; ; i++){ StringTokenizer st = new StringTokenizer(report[i]); String snitch = st.nextToken(); String suspect = st.nextToken(); snitch_list.compute(suspect, (key,ov) -> { if(ov == null) ov = new HashSet<>(); ov.add(snitch); return ov; }); cnt.compute(suspect, (key,ov) -> (ov == null? 1 : ov+1)); snitch = ""; }
위의 코드는 그냥 snitch를 같은 코드 내에 재할당했으므로, 람다식 캡쳐링 조건에 걸려서 오류가 난다.
String snitch; for(int i = 0; i <report.length; ; i++){ StringTokenizer st = new StringTokenizer(report[i]); snitch = st.nextToken(); String suspect = st.nextToken(); snitch_list.compute(suspect, (key,ov) -> { if(ov == null) ov = new HashSet<>(); ov.add(snitch); return ov; }); cnt.compute(suspect, (key,ov) -> (ov == null? 1 : ov+1)); snitch = ""; }
위의 코드 또한 루프마다 변수를 새로 만드는 것이 아니라, 재할당하는 것이므로 람다식 캡쳐링 조건에 걸려 오류가 난다.