📑 1. 문제설명





💡 2. 풀이과정
문제에서 매개변수는 이용자 ID가 담긴 `id_list`, 각 이용자가 신고한 이용자의 ID가 담긴 문자열 배열 `report`, 그리고 정지 기준이 되는 신고 횟수 `k` 이다.
구하고자 하는 것은 각 유저별로 처리 결과 메일을 받은 횟수를 배열 형식으로 리턴하는 것이다.
이것을 Canva로 그림으로 나타내보면 아래와 같다.

- muzi를 신고한 사람 : apeach (1)
- frodo를 신고한 사람 : muzi, apeach (2)
- apeach를 신고한 사람 : 없음 (0)
- neo를 신고한 사람 : muzi, frodo (2)
해시맵으로 푸는 문제라는 걸 알 수 있다.
키는 신고를 당한 유저, 값은 신고한 유저로 구성하면 된다.
이 때 문제에 `한 유저를 여러 번 신고해도 신고 횟수가 1회로 처리된다`는 조건이 있다. 즉, 해시맵의 value 값에 중복이 있으면 안된다. 쉽게 말해서 만약에 apeach가 신고당했다고 가정 해 보자. 키값이 apeach라면 신고한 사람(value)가 muzi, muzi, muzi가 될 수는 없다는 것이다. 그냥 muzi 한 개만 온다는 것이다. 그렇기 때문에 해시맵의 value는 중복이 없는 HashSet을 쓰자.
그런데 여기서 헷갈리는 건 리턴할 값이 [1, 2, 0, 2] 가 아니라, 처리결과 메일의 수를 리턴하는 것이다. 누가 k번 이상 신고당해서 정지당했는가에서 끝나는게 아니라, 정지당한 유저가 있다면 그 사람을 신고한 유저에게 결과 통보 메일을 보낼 횟수를 구하는 것이다. 위 예시의 경우, frodo랑 neo를 둘 다 신고한 사람은 메일을 2번 받게 되고, 둘 중에 한 명만 신고한 사람은 메일 1번을 받는다. 즉 리턴할 값은 [2, 1, 1, 0] 이다.
그래서 신고자별로 메일 받을 횟수를 저장할 해시맵 cnt를 하나 더 선언 해 주어야 한다.
먼저 해시맵을 돌면서 각 이름에 대해서 신고자가 k명 이상인지 확인한다.
그 후, 만약 k명 이상이면 cnt의 value 값을 증가한다.

👨💻 3. 정답코드
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
// 신고 당한 사람(key) - 신고한 사람(value)
HashMap<String, HashSet<String>> reportedUser = new HashMap<>();
// 신고한사람 - 메일 받을 횟수
HashMap<String, Integer> cnt = new HashMap<>();
// 신고 기록 저장
for (String r : report) {
String[] name = r.split(" ");
String reportUser = name[0];
String reported = name[1];
if (!reportedUser.containsKey(reported)) {
reportedUser.put(reported, new HashSet<>());
} else {
// 신고자를 해시맵의 value(해시셋)에 추가
reportedUser.get(reported).add(reportUser);
}
}
for(Map.Entry<String, HashSet<String>> entry : reportedUser.entrySet()) {
if (entry.getValue().size() >= k) { // 정지 기준
for (String user : entry.getValue()) {
cnt.put(user, cnt.getOrDefault(user, 0) +1);
}
}
}
int[] answer = new int[id_list.length];
for (int i = 0 ; i < id_list.length; i++) {
answer[i] = cnt.getOrDefault(id_list[i], 0);
}
return answer;
}
}

코드 모든 결과값이 0으로 나옴..
왜? 신고 목록이 비어 있어서 아무도 정지되지 않은 것....
reportedUser에 새로운 사용자를 추가할 때 처음 신고한 사용자의 정보가 저장 안 됨
왜냐하면 if문을 잘못 써서 else 블록에서만 add()를 실행하기 때문에, 첫 번째 신고는 추가가 아예 안된 것이다.
이 부분을 잘못씀....
기존에 없으면 새로 생성 후 추가해야 하는데 else문 안에 value에 추가하는 코드를 씀...
if (!reportedUser.containsKey(reported)) {
reportedUser.put(reported, new HashSet<>());
} else {
reportedUser.get(reported).add(reportUser);
}
이 부분을 아래처럼 수정해 주었다.
if (!reportedUser.containsKey(reported)) {
reportedUser.put(reported, new HashSet<>());
}
reportedUser.get(reported).add(reportUser);
}
chatGPT에서 찾아보니까 `putIfAbsent` 라는 메서드가 있다.
if문 대신 이 메서드를 쓰면 코드가 더 깔끔하다.
reportedUser.putIfAbsent(reported, new HashSet<>());
reportedUser.get(reported).add(reportUser);
다른 코드를 찾아보니까 처음에 cnt를 0으로 초기화해주는게 좋다고 한다.
모든 id_list에 대해 cnt.put(id, 0); 을 하지 않으면 값이 없을때 `null`이 반환될수도 있다고 한다.
나는 이미 cnt.put(user, cnt.getOrDefault(user, 0) + 1);를 했기 때문에 별도로 카운트를 초기화 하지 않았다. 결과 배열을 만들 때도 cnt.get(id_list[i])를 하면 NullPointerException이 발생할 수 있다고 하는데, 이 때도 마찬가지로 cnt.get(id_list[i]) 대신 getOrDefault를 쓸 수 있다. 하지만 나의 코드에서는 answer[i] = cnt.get(id_list[i]); 만 해도 NullPointerException이 걸릴 가능성은 없다.
answer[i] = cnt.get(id_list[i]); // 여기서 NullPointerException 가능성 있음
answer[i] = cnt.getOrDefault(id_list[i], 0);
진짜 정답코드
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
// 신고 당한 사람(key) - 신고한 사람(value)
HashMap<String, HashSet<String>> reportedUser = new HashMap<>();
// 신고한사람 - 메일 받을 횟수
HashMap<String, Integer> cnt = new HashMap<>();
// 신고 기록 저장
for (String r : report) {
String[] name = r.split(" ");
String reportUser = name[0];
String reported = name[1];
if (!reportedUser.containsKey(reported)) {
reportedUser.put(reported, new HashSet<>());
}
reportedUser.get(reported).add(reportUser);
}
for(Map.Entry<String, HashSet<String>> entry : reportedUser.entrySet()) {
if (entry.getValue().size() >= k) { // 정지 기준
for (String user : entry.getValue()) {
cnt.put(user, cnt.getOrDefault(user, 0) +1);
}
}
}
int[] answer = new int[id_list.length];
for (int i = 0 ; i < id_list.length; i++) {
answer[i] = cnt.getOrDefault(id_list[i], 0);
}
return answer;
}
}
'코딩테스트 > JAVA테스트' 카테고리의 다른 글
[프로그래머스] (Java) 숫자 찾기 (숫자를 문자로) (2) | 2025.05.20 |
---|---|
[프로그래머스] (Java) 배열의 유사도 (4) | 2025.05.20 |
[프로그래머스] (Java) 369게임 문제풀이 (16) | 2025.03.31 |
[프로그래머스] (Java) 가까운 수 문제풀이 (6) | 2025.03.31 |
[프로그래머스] (Java) 삼각형의 완성조건(1) 문제풀이 (4) | 2025.03.31 |
📑 1. 문제설명





💡 2. 풀이과정
문제에서 매개변수는 이용자 ID가 담긴 id_list
, 각 이용자가 신고한 이용자의 ID가 담긴 문자열 배열 report
, 그리고 정지 기준이 되는 신고 횟수 k
이다.
구하고자 하는 것은 각 유저별로 처리 결과 메일을 받은 횟수를 배열 형식으로 리턴하는 것이다.
이것을 Canva로 그림으로 나타내보면 아래와 같다.

- muzi를 신고한 사람 : apeach (1)
- frodo를 신고한 사람 : muzi, apeach (2)
- apeach를 신고한 사람 : 없음 (0)
- neo를 신고한 사람 : muzi, frodo (2)
해시맵으로 푸는 문제라는 걸 알 수 있다.
키는 신고를 당한 유저, 값은 신고한 유저로 구성하면 된다.
이 때 문제에 한 유저를 여러 번 신고해도 신고 횟수가 1회로 처리된다
는 조건이 있다. 즉, 해시맵의 value 값에 중복이 있으면 안된다. 쉽게 말해서 만약에 apeach가 신고당했다고 가정 해 보자. 키값이 apeach라면 신고한 사람(value)가 muzi, muzi, muzi가 될 수는 없다는 것이다. 그냥 muzi 한 개만 온다는 것이다. 그렇기 때문에 해시맵의 value는 중복이 없는 HashSet을 쓰자.
그런데 여기서 헷갈리는 건 리턴할 값이 [1, 2, 0, 2] 가 아니라, 처리결과 메일의 수를 리턴하는 것이다. 누가 k번 이상 신고당해서 정지당했는가에서 끝나는게 아니라, 정지당한 유저가 있다면 그 사람을 신고한 유저에게 결과 통보 메일을 보낼 횟수를 구하는 것이다. 위 예시의 경우, frodo랑 neo를 둘 다 신고한 사람은 메일을 2번 받게 되고, 둘 중에 한 명만 신고한 사람은 메일 1번을 받는다. 즉 리턴할 값은 [2, 1, 1, 0] 이다.
그래서 신고자별로 메일 받을 횟수를 저장할 해시맵 cnt를 하나 더 선언 해 주어야 한다.
먼저 해시맵을 돌면서 각 이름에 대해서 신고자가 k명 이상인지 확인한다.
그 후, 만약 k명 이상이면 cnt의 value 값을 증가한다.

👨💻 3. 정답코드
import java.util.HashMap; import java.util.HashSet; import java.util.Map; class Solution { public int[] solution(String[] id_list, String[] report, int k) { // 신고 당한 사람(key) - 신고한 사람(value) HashMap<String, HashSet<String>> reportedUser = new HashMap<>(); // 신고한사람 - 메일 받을 횟수 HashMap<String, Integer> cnt = new HashMap<>(); // 신고 기록 저장 for (String r : report) { String[] name = r.split(" "); String reportUser = name[0]; String reported = name[1]; if (!reportedUser.containsKey(reported)) { reportedUser.put(reported, new HashSet<>()); } else { // 신고자를 해시맵의 value(해시셋)에 추가 reportedUser.get(reported).add(reportUser); } } for(Map.Entry<String, HashSet<String>> entry : reportedUser.entrySet()) { if (entry.getValue().size() >= k) { // 정지 기준 for (String user : entry.getValue()) { cnt.put(user, cnt.getOrDefault(user, 0) +1); } } } int[] answer = new int[id_list.length]; for (int i = 0 ; i < id_list.length; i++) { answer[i] = cnt.getOrDefault(id_list[i], 0); } return answer; } }

코드 모든 결과값이 0으로 나옴..
왜? 신고 목록이 비어 있어서 아무도 정지되지 않은 것....
reportedUser에 새로운 사용자를 추가할 때 처음 신고한 사용자의 정보가 저장 안 됨
왜냐하면 if문을 잘못 써서 else 블록에서만 add()를 실행하기 때문에, 첫 번째 신고는 추가가 아예 안된 것이다.
이 부분을 잘못씀....
기존에 없으면 새로 생성 후 추가해야 하는데 else문 안에 value에 추가하는 코드를 씀...
if (!reportedUser.containsKey(reported)) { reportedUser.put(reported, new HashSet<>()); } else { reportedUser.get(reported).add(reportUser); }
이 부분을 아래처럼 수정해 주었다.
if (!reportedUser.containsKey(reported)) { reportedUser.put(reported, new HashSet<>()); } reportedUser.get(reported).add(reportUser); }
chatGPT에서 찾아보니까 putIfAbsent
라는 메서드가 있다.
if문 대신 이 메서드를 쓰면 코드가 더 깔끔하다.
reportedUser.putIfAbsent(reported, new HashSet<>()); reportedUser.get(reported).add(reportUser);
다른 코드를 찾아보니까 처음에 cnt를 0으로 초기화해주는게 좋다고 한다.
모든 id_list에 대해 cnt.put(id, 0); 을 하지 않으면 값이 없을때 null
이 반환될수도 있다고 한다.
나는 이미 cnt.put(user, cnt.getOrDefault(user, 0) + 1);를 했기 때문에 별도로 카운트를 초기화 하지 않았다. 결과 배열을 만들 때도 cnt.get(id_list[i])를 하면 NullPointerException이 발생할 수 있다고 하는데, 이 때도 마찬가지로 cnt.get(id_list[i]) 대신 getOrDefault를 쓸 수 있다. 하지만 나의 코드에서는 answer[i] = cnt.get(id_list[i]); 만 해도 NullPointerException이 걸릴 가능성은 없다.
answer[i] = cnt.get(id_list[i]); // 여기서 NullPointerException 가능성 있음
answer[i] = cnt.getOrDefault(id_list[i], 0);
진짜 정답코드
import java.util.HashMap; import java.util.HashSet; import java.util.Map; class Solution { public int[] solution(String[] id_list, String[] report, int k) { // 신고 당한 사람(key) - 신고한 사람(value) HashMap<String, HashSet<String>> reportedUser = new HashMap<>(); // 신고한사람 - 메일 받을 횟수 HashMap<String, Integer> cnt = new HashMap<>(); // 신고 기록 저장 for (String r : report) { String[] name = r.split(" "); String reportUser = name[0]; String reported = name[1]; if (!reportedUser.containsKey(reported)) { reportedUser.put(reported, new HashSet<>()); } reportedUser.get(reported).add(reportUser); } for(Map.Entry<String, HashSet<String>> entry : reportedUser.entrySet()) { if (entry.getValue().size() >= k) { // 정지 기준 for (String user : entry.getValue()) { cnt.put(user, cnt.getOrDefault(user, 0) +1); } } } int[] answer = new int[id_list.length]; for (int i = 0 ; i < id_list.length; i++) { answer[i] = cnt.getOrDefault(id_list[i], 0); } return answer; } }
'코딩테스트 > JAVA테스트' 카테고리의 다른 글
[프로그래머스] (Java) 숫자 찾기 (숫자를 문자로) (2) | 2025.05.20 |
---|---|
[프로그래머스] (Java) 배열의 유사도 (4) | 2025.05.20 |
[프로그래머스] (Java) 369게임 문제풀이 (16) | 2025.03.31 |
[프로그래머스] (Java) 가까운 수 문제풀이 (6) | 2025.03.31 |
[프로그래머스] (Java) 삼각형의 완성조건(1) 문제풀이 (4) | 2025.03.31 |