본문 바로가기

개발지/코테

[프로그래머스] 코테연습 - 신고 결과 받기

- 내 방법 풀이

  • 처음 시간 초과가 난 코드이다. 신고 당한 횟수가 k번 이상인 유저의 신고자들의 메일을 보내는 것이, 정말 헷갈렸다. 어떻게 구현해야 할 지 모르겠어서 생각나는데로 hashSet을 순회하며 answer[idx]를 증가시켰지만 3 9 10 11 14 20 21번 총 6개의 케이스에서 시간 초과가 되었다.
import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        Set<String> hashSet = new HashSet<>();
        for (String S : report) {
            hashSet.add(S);
        }

        HashMap<String, Integer> reportNum = new HashMap<>();
        for (String S : hashSet) {
            String[] arr = S.split(" ");
            if (reportNum.containsKey(arr[1])) reportNum.put(arr[1], reportNum.get(arr[1]) + 1);
            else reportNum.put(arr[1], 1);
        }
        
        for (int i = 0; i < answer.length; i++) {
            if (reportNum.containsKey(id_list[i]) && reportNum.get(id_list[i]) >= k) { // 해당 유저가 신고목록에 있으며. 신고횟수가 k번 이상인 경우 
                for (String S : hashSet) { // hashSet에서 해당 유저를 신고한 유저의 메일 발송 횟수 증가.
                    String[] arr = S.split(" ");
                    String reportid = arr[0];
                    int idIdx = findidx(id_list, reportid);
                    if (arr[1].equals(id_list[i])) answer[idIdx]++;
                }
            }
        }
        return answer;
    }
    
    public int findidx (String[] idList, String id) {
        return Arrays.asList(idList).indexOf(id);
    }
}
  • 처리 결과를 받을 유저를 조회하는 과정을 다시 짤 필요가 있었다. 
  • 처리 결과를 받을 유저를 조회하기 위해, 신고받은 유저별로 해당 유저를 신고한 유저들을 저장할 ArrayList를 값으로 가지는 Map을 사용했다. 유저별로 IDidx를 저장하는 map도 만들었다. 
  • Set을 통해 중복을 없앤 뒤, reportedId에서 신고한 유저들도 저장해주었다. 신고한 유저들의 수가 k이상일 경우 배열을 순회하여, idIdx에 저장된 idx에 따라 answer[idx]를 증가시켜주었다.
import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length]; // id갯수와 같은 길이의 answer 생성.
        HashSet<String> report_Set = new HashSet<>();
        Map<String, ArrayList<String>> reportedId = new HashMap<>();
        Map<String, Integer> idIdx = new  HashMap<>();
        
        for (int i = 0; i < id_list.length; i++) { 
            idIdx.put(id_list[i], i);
            reportedId.put(id_list[i], new ArrayList<>());
        }
        
        for (String reported : report) { // hashset으로 중복 제거.
            report_Set.add(reported);
        }
        
        for (String reported : report_Set) { // 신고받은 아이디별로 신고자목록 저장.
            String[] tmp = reported.split(" ");
            String reporterName = tmp[0];
            String reportedName = tmp[1];
            reportedId.get(reportedName).add(reporterName);
        }
        
        for (String id : id_list) { // hashMap 순회하면서 ArrayList.size가 k이상일 때, ArrayList에서 신고한 사람의 처리 결과 int 증가
            ArrayList<String> tmp = reportedId.get(id);
            if (tmp.size() >= k) { // 신고횟수 k 이상
                for (String name : tmp) {
                    answer[idIdx.get(name)]++; // 해당 유저의 처리 횟수 증가
                }
            }
        }
        return answer;
    }
}

 

- 다른 사람 방법 풀이 1

  • 개인적으로 이해하기 쉬웠던 코드.
  • 내가 배열을 사용해서 받은 것과 다르게 List를 사용했고, contains를 사용해서 신고가 중복되는 것을 피했다.
  • 이후 풀이는 비슷했다.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        Map<String, Integer> idIndex = new HashMap<>();
        Map<String, List<String>> reportMap = new HashMap<>();

        for (int i = 0; i < id_list.length; i++) {
            idIndex.put(id_list[i], i);
            reportMap.put(id_list[i], new ArrayList<>());
        }

        for (String reported : report) {
            String[] temp = reported.split(" ");
            if (!reportMap.get(temp[1]).contains(temp[0])) {
                reportMap.get(temp[1]).add(temp[0]);
            }
        }

        for (String id : reportMap.keySet()) {
            if (k <= reportMap.get(id).size()) {
                for (String reporter : reportMap.get(id)) {
                    answer[idIndex.get(reporter)]++;
                }
            }
        }

        return answer;
    }
}

 

 

- 다른 사람 방법 풀이 2

  • User 클래스를 분리하여 많은 사람들이 감탄한 코드. & 객체 지향적인 코드
  • 여러 풀이 코드들을 보다 보면, 하나의 문제를 풀 때 정말 다양한 방법들이 있구나 라는 생각이 든다. 코드들은 보면서 나의 풀이와 다른 또다른 풀이가 생각나기도 한다.
import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        ArrayList<User> users = new ArrayList<>();
        HashMap<String,Integer> suspendedList = new HashMap<>(); //<이름>
        HashMap<String,Integer> idIdx = new HashMap<String,Integer>(); // <이름, 해당 이름의 User 클래스 idx>
        int idx = 0;

        for(String name : id_list) {
            idIdx.put(name,idx++);
            users.add(new User(name));
        }

        for(String re : report){
            String[] str = re.split(" ");
            //suspendedCount.put(str[0], suspendedCount.getOrDefault(str[0],0)+1);
            users.get( idIdx.get(str[0])).reportList.add(str[1]);
            users.get( idIdx.get(str[1])).reportedList.add(str[0]);
        }

        for(User user : users){
            if(user.reportedList.size() >= k)
                suspendedList.put(user.name,1);
        }

         for(User user : users){
             for(String nameReport : user.reportList){
                 if(suspendedList.get(nameReport) != null){
                     answer[idIdx.get(user.name)]++;
                 }

             }
        }




        return answer;
    }
}

class User{
    String name;
    HashSet<String> reportList;
    HashSet<String> reportedList;
    public User(String name){
        this.name = name;
        reportList = new HashSet<>();
        reportedList = new HashSet<>();
    }
}