프로그래머스 에서 코딩테스트 문제 신고 결과 받기 를 풀어봤습니당~
1단계입니당!
https://programmers.co.kr/learn/courses/30/lessons/92334?language=java
문제 설명
신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.
- 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
- 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
- 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 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_listreportkresult
["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 합니다.
🚨 문제 풀이
중속 신고를 제거하기 위해 HashMap, HashSet 을 사용
Set : 데이터를 중복 저장할 수 없고, 입력 순서대로의 저장순서를 보장 받을 수 없는 자료구조
HashSet : Set 인터페이스를 구현. 순서가 필요없는 데이터를 hash table 에 저장. Set 중 가장 성능이 좋고, put() 메소드를 사용해 데이터를 넣는다. HashMap 인스턴스를 사용한다.
HashMap : Map 인터페이스를 구현. key-value 형식의 데이터를 저장. 중복된 key 값을 허용하지 않는다. add() 메소드를 사용해 데이터를 넣는다.
reportedMap : [신고된ID, [신고한ID들]] 로 구성된 HashMap
- key 는 유저ID(신고된ID), value 는 중복 허용을 하지 않는 HashSet 으로 사용
answerMap : [신고된ID, 메일 수] 로 구성된 HashMap
최종적으로 answer 에는 answerMap 의 key 별 value 값의 1차원 배열이 들어간다
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
class Solution {
public static int[] solution(String[] id_list, String[] report, int k) {
int[] answer = {};
answer = new int[id_list.length];
/*
* key 는 유저ID
* value 는 신고한 유저ID의 set 을 가진 map
* 동일한 유저ID에 대한 신고횟수는 1회로 처리하기 때문에 중복 허용을 하지 않는 set 을 value 로 사용
* */
Map<String, HashSet<String>> reportedMap = new HashMap<>(); // [신고된ID, [신고한ID]]
Map<String, Integer> answerMap = new HashMap<>(); // [신고된Id, 메일 수]
/* 1. Map 초기화 */
for (int i = 0; i < id_list.length; i++) {
HashSet<String> reportingId = new HashSet<>(); // 신고한ID
reportedMap.put(id_list[i], reportingId); // 유저ID, 신고한ID 초기 세팅
answerMap.put(id_list[i], 0); // 메일 수는 모두 0 으로 초기화
}
System.out.println("[STEP 1] reportedMap : " + reportedMap);
System.out.println("[STEP 1] answerMap : " + answerMap);
/*
* 2. 신고 기록 세팅 report 는 "신고한ID 신고된ID" 로 구성됨
*/
for (String s : report) {
String[] reportStr = s.split(" ");
String reportingID = reportStr[0]; // 신고한ID
String reportedID = reportStr[1]; // 신고된ID
reportedMap.get(reportedID).add(reportingID); // 신고된ID 를 key 값으로 신고한ID 배열을 value 로 새팅
}
System.out.println("[STEP 2] reportedMap 에 신고 기록 세팅 : " + reportedMap);
/*
* 3. 유저가 받은 이용 정지 결과 메일 세팅
*/
for (String reportedUser : reportedMap.keySet()) { // reportedUser 는 신고된ID유저
HashSet<String> userForSend = reportedMap.get(reportedUser); // reportedUser(신고된유저)를 신고한 유저
if (userForSend.size() >= k) { // 신고된 횟수가 K번 이상일 경우
for (String userId : userForSend) {
answerMap.put(userId, answerMap.get(userId) + 1); // answerMap 에 신고된Id 별 메일 수 넣기
}
}
}
System.out.println("[STEP 3] answerMap 에 메일 수 세팅 : " + answerMap);
/*
* 4. 유저ID 별 받은 메일 수를 answer 에 세팅
*/
for (int i = 0; i < id_list.length; i++) {
answer[i] = answerMap.get(id_list[i]);
System.out.println("[STEP 4] answer : " + answer[i]);
}
return answer;
}
}
출력 결과
테스트 1 | |
입력값 〉 | ["muzi", "frodo", "apeach", "neo"], ["muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi"], 2 |
기댓값 〉 | [2, 1, 1, 0] |
실행 결과 〉 | 테스트를 통과하였습니다. |
출력 〉 | [STEP 1] reportedMap : {muzi=[], neo=[], frodo=[], apeach=[]} [STEP 1] answerMap : {muzi=0, neo=0, frodo=0, apeach=0} [STEP 2] reportedMap 에 신고 기록 세팅 : {muzi=[apeach], neo=[muzi, frodo], frodo=[muzi, apeach], apeach=[]} [STEP 3] answerMap 에 메일 수 세팅 : {muzi=2, neo=0, frodo=1, apeach=1} [STEP 4] answer : 2 [STEP 4] answer : 1 [STEP 4] answer : 1 [STEP 4] answer : 0 |
테스트 2 | |
입력값 〉 | ["con", "ryan"], ["ryan con", "ryan con", "ryan con", "ryan con"], 3 |
기댓값 〉 | [0, 0] |
실행 결과 〉 | 테스트를 통과하였습니다. |
출력 〉 | [STEP 1] reportedMap : {ryan=[], con=[]} [STEP 1] answerMap : {ryan=0, con=0} [STEP 2] reportedMap 에 신고 기록 세팅 : {ryan=[], con=[ryan]} [STEP 3] answerMap 에 메일 수 세팅 : {ryan=0, con=0} [STEP 4] answer : 0 [STEP 4] answer : 0 |
감사합니당
'🧪 알고리즘 ~ 코딩테스트' 카테고리의 다른 글
[프로그래머스] 추억 점수 (Java/Kotlin) - Lv.1 (0) | 2024.01.27 |
---|---|
[프로그래머스] 콜라문제(Kotlin) - Lv.1 (1) | 2023.10.21 |
[ 프로그래머스 ] 신규 아이디 추천(Java) - 2021 KAKAO BLIND RECRUITMENT / 정규표현식(replaceAll 를 사용한 문자열 치환) (0) | 2022.05.11 |
[ 프로그래머스 ] 완주하지 못한 선수(Java) (0) | 2021.03.26 |
[ 프로그래머스 ] 크레인 인형뽑기 게임(Java) (0) | 2021.03.25 |