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

LeeYulhee·2023년 8월 28일
0

💻 문제 출처 : 프로그래머스_신고 결과 받기

👉 내가 작성한 답


import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        
        // 이름을 Key로, String Set을 Value로 갖는 Map 생성
        // => Key의 이름을 신고한 사람 Set을 저장됨
        // => Key에 해당하는 Set size가 k 이상이면 해당 Set에 있는 사람들에 대한 answer 배열 요소를 + 1
        
        Map<String, Set<String>> reportMap = new HashMap<>();
        
        for(String s : id_list) {
            reportMap.put(s, new HashSet<>());
        }
        
        for(String s : report) {
            String[] division = s.split(" ");
            
            String reporter = division[0];
            String badman = division[1];
            reportMap.get(badman).add(reporter);
        }
        
        for(String s : id_list) {
            if(reportMap.get(s).size() >= k) {
                for(String reporter : reportMap.get(s)) {
                    int index = 0;
                    for(int i = 0; i < id_list.length; i++) {
                        if(id_list[i].equals(reporter)) {
                            index = i;
                            break;
                        }
                    }
                    
                    answer[index] += 1;
                }
            }
        }
        
        return answer;
    }
}

📌 문제 풀이 설명

  • int 배열 answer를 id_list의 길이로 생성
  • String을 Key로, Set을 Value로 갖는 Map을 생성
  • 향상된 for문으로 id_list를 순회
    • Map에 id_list의 요소를 Key로, Set의 객체를 Value로 넣음
  • 향상된 for문으로 report를 순회
    • String 배열 division에 report의 요소를 “ “로 나눈 값을 넣음
    • String 변수 reporter에 신고자인 division[0]을 대입
    • String 변수 badman에 신고 당한 사람인 division[1]을 대입
    • Map에서 badman에 해당하는 Set을 가져와 reporter를 추가
  • 향상된 for문으로 id_list를 순회
    • 만약 id_list의 요소에 해당하는 Map의 Set 크기가 k 보다 크거나 같으면
      • 향상된 for문으로 Map에서 s에 해당하는 Set을 순회
        • int index 변수를 선언하고 0으로 초기화
        • for문으로 0부터 id_list의 길이 미만까지 1씩 증가하며 순회
          • 만약 id_list[i]가 reporter와 같은 경우
            • index에 i를 대입하고 break로 for문 종료
        • answer[index]에 1 증가
  • for문 종료 후 return answer



👉 다른 사람이 작성한 답 - 1


import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        List<String> list = Arrays.stream(report).distinct().collect(Collectors.toList());
        HashMap<String, Integer> count = new HashMap<>();
        for (String s : list) {
            String target = s.split(" ")[1];
            count.put(target, count.getOrDefault(target, 0) + 1);
        }

        return Arrays.stream(id_list).map(_user -> {
            final String user = _user;
            List<String> reportList = list.stream().filter(s -> s.startsWith(user + " ")).collect(Collectors.toList());
            return reportList.stream().filter(s -> count.getOrDefault(s.split(" ")[1], 0) >= k).count();
        }).mapToInt(Long::intValue).toArray();
    }
}

📌 문제 풀이 설명

  • String List를 선언해서 report 배열을 스트림으로 변환 → distinct로 중복 값을 제거(한 사용자가 같은 사람을 여러 번 신고한 경우 제거) → List로 변환한 값을 대입
  • String을 Key로, Integer를 Value로 갖는 Map을 생성
  • 향상된 for문으로 list를 순회
    • String target에 list의 요소를 “ “를 나눈 값의 1번 인덱스에 해당하는 값을 대입(신고 당한 사람)
    • Map에 target을 Key로, Map에서 target으로 가져온 값이 없으면 0, 있으면 해당 값에 + 1을 해서 put
  • for문 종료 후 return 과정
    • id_list를 스트림으로 변환 → 람다식 내부에서 사용될 변수는 변경 불가능해야 하기 때문에 _user를 final 변수 user에 대입
    • String을 값으로 받는 List를 reportList라는 이름으로 생성 → list를 stream으로 변환 → filter로 user(이름) + “ “로 시작하는 문자만 필터링 → List로 변환해서 대입(해당 user가 신고한 내역을 list로 만든 것)
    • reportList를 stream으로 변환 → filter로 count Map에 s를 “ “로 나눈 값의 1번 인덱스(신고된 내역)로 조회했을 때 없으면 0을, 있으면 해당 값을 가져와서 k보다 크거나 같을 때만 필터링 → count해서 return
      • k번 이상 신고된 경우 그 개수를 return
    • 앞의 과정을 계산한 값을 int로 변환 → 배열로 변환해 return



👉 다른 사람이 작성한 답 - 2


import java.util.*;
class Solution {
 public int[] solution(String[] id_list, String[] report, int k) {
        // key: 신고당한놈, value: 몇명한테 당했는지
        Map<String, Set<String>> map = new HashMap<>();

        for (String rep : report) {
            String[] arr = rep.split(" ");
            Set<String> set = map.getOrDefault(arr[1], new HashSet<>());
            set.add(arr[0]);
            map.put(arr[1], set);
        }

        // key: 알림받을 놈, value: 몇번 알림받을지
        Map<String, Integer> countMap = new LinkedHashMap<>();

        for (String id : id_list) {
            countMap.put(id, 0);
        }

        for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
            if (entry.getValue().size() >= k) { // 정지당할놈
                for (String value : entry.getValue()) {
                    countMap.put(value, countMap.getOrDefault(value, 0) + 1);
                }
            }
        }

        return countMap.values().stream().mapToInt(Integer::intValue).toArray();
    }
}

📌 문제 풀이 설명

  • String을 Key로, String Set을 Value로 갖는 Map 생성
  • 향상된 for문으로 report를 순회
    • String 배열 arr에 report의 요소를 “ “로 나눈 값을 대입
    • Set set 변수에 map에서 getOrDefault 메서드로 arr[1]에 해당하는 Set을 대입하거나 없으면 새로운 Set 객체를 생성해서 대입
      • arr[1]은 신고 당한 사람
    • set에 arr[0]을 추가(신고한 사람)
    • map에 arr[1]과 set을 넣음
  • String을 Key로, Integer를 Value로 갖는 LinkedHashMap을 countMap이라는 이름으로 생성
  • 향상된 for문으로 id_list를 순회
    • countMap에 id와 0을 넣음
      • 초기 값 설정
  • 향상된 for문으로 map의 entrySet 메서드를 이용해 Map의 Entry<String, Set>으로 변환해서 순회
    • ➕ Map.Entry와 entrySet
      • Map은 키-값 쌍으로 이루어져 있는데, 해당 값들을 순회하려면 entrySet()을 사용하여 각 키-값 쌍에 대한 정보를 얻을 수 있음
      • 이 키-값 쌍은 Map.Entry<K, V>타입으로 표현됨
        • K는 키의 타입, V는 값의 타입
        • Map.Entry<K, V>는 java.util.Map 인터페이스의 내부 인터페이스로 Map에 저장된 각 키-값 쌍을 나타내기 위한 표현
      • getKey() 메서드로 키를 얻을 수 있음
      • getValue() 메서드로 값을 얻을 수 있음
    • 만약 entry의 값(Set)의 크기가 k보다 크거나 같다면
      • 향상된 for문으로 entry의 값(Set)을 순회
        • countMap에 put으로 Set의 요소를 Key로, countMap에서 getOrDefault로 Set의 요소가 Key로 조회했을 때 값이 없다면 0을, 아니면 해당하는 값을 받아와 + 1해서 넣음
  • for문 종료 후 countMap의 값을 int로 변환 → 배열로 변환해 return



👉 다른 사람이 작성한 답 - 3


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<>();
    }
}

📌 문제 풀이 설명

  • int 배열 answer를 id_list의 길이로 생성
  • User를 값으로 사용하는 ArrayList를 생성
    • User 클래스
      • String name과 String Set reportList, String Set reportedList를 변수로 선언
      • String name을 매개변수로 받는 생성자를 선언
        • 클래스의 name에 매개변수로 들어온 name을 대입
        • reportList와 reportedList에 새로운 Set 객체를 생성해 대입
  • String을 Key로, Integer를 Value로 갖는 Map을 suspendedList라는 이름으로 생성
  • String을 Key로, Integer를 Value로 갖는 Map을 idIdx라는 이름으로 생성
  • int 변수 idx를 선언하고 0으로 초기화
  • 향상된 for문으로 id_list 순회
    • idIdx에 name을 key로, idx를 값으로 넣고 idx 1 증가
      • 각 이름에 해당하는 배열 인덱스 저장
    • users에 name을 매개변수로 넣은 User 객체를 생성해 추가
  • 향상된 for문으로 report를 순회
    • String 배열에 report의 요소를 “ “으로 나눈 값을 대입
    • idIdx에서 str[0]에 해당하는 value(해당 이름의 index)를 users에서 인덱스로 사용해 값을 가져옴(User 객체) → User 객체의 reportList에 str[1]을 추가
      • str[0]은 신고한 사람으로 여기서는 User 객체의 당사자
      • str[1]은 신고 당한 사람으로 reportList에 추가하는 것
    • idIdx에서 str[1]에 해당하는 value(해당 이름의 index)를 users에서 인덱스로 사용해 값을 가져옴(User 객체) → User 객체의 reportedList에 str[0]을 추가
      • 신고 당한 사람의 reportedList에 신고한 사람을 추가
  • 향상된 for문으로 users를 순회
    • 만약 user의 reportedList의 크기가 k 보다 크거나 같으면(user를 신고한 사람)
      • suspendedList에 user의 이름과 1을 넣음
  • 향상된 for문으로 users를 순회
    • 향상된 for문으로 user의 reportList를 순회
      • 만약 suspendedList에 user의 reportList 요소로 가져온 값이 null이 아니면(k번 이상 신고 당한 사람)
        • idIdx에서 user의 이름으로 가져온 값을 answer의 index로 사용하여 해당 값에 1 증가
  • for문 종료 후 return answer
profile
공부 중인 신입 백엔드 개발자입니다

0개의 댓글