알고리즘/코딩테스트(카카오)

2022KAKAO BLIND RECRUITMENT[신고결과받기]_해시LV.1

Leo.K 2022. 4. 26. 00:06

 

문제와 예시를 읽어보면 생각보다 복잡하지 않은 문제입니다. 필자는 중복을 제거하기 위해 HashSet을 사용했습니다. 문제를 읽어보고 지켜야할 조건을 분석해보면 다음과 같습니다. 

  • 한 번에 한 명의 사용자만 신고할 수 있다. 
  • 같은 사람에게 여러 번 신고당한 경우 1이상 count하지 않는다. 
  • k번 이상 신고를 당한 사람은 이용이 정지당하며, 이용이 정지당한 사람을 신고한 사람에게 메일을 보낸다. 
  • 이때 id_list에 있는 사람들의 각각 메일을 받은 횟수를 count해야 한다. 

 

위의 조건들을 살펴보자면 일단 중복을 제거해야 합니다. 중복의 조건은 신고 당한 사람을 기준으로 해당 사람을 신고한 사람이 중복되면 안됩니다. -> 필자는 이 부분에서 HashSet을 사용하기로 마음먹었습니다. 

report의 요소를 보니 문자열을 분리해야 함을 느꼈고, 이를 2차원배열에 넣을까 하다가 HashMap에 저장하기로 했습니다. 

반환값이 배열이므로, 인덱스를 참조해야 겠다는 생각을 했는데, 자료구조로 HashMap을 골라서 어떻게 활용할까 하다가 id_list에 저장된 인덱스 순서 그대로 반환값 answer배열에 담기 위해서 또 다른 HashMap에 사용자id와 그 사람의 위치를 기억할 수 있도록 배열의 index값을 함께 저장했습니다. 

코드로 보면 다음과 같습니다. 주석과 함께 보시면 이해하는데는 어려움이 없을겁니다.

1. 변수 셋팅 및 초기화

1
2
3
4
5
6
7
8
9
10
        //리스트에 있는 유저명과 배열의 인덱스값을 저장
        HashMap<String, Integer> mapIdx = new HashMap<String, Integer>();
        //신고당한 유저와 이 사람을 신고한 유저들을 저장
        HashMap<String, HashSet<String>> map = new HashMap<>();
        
//기본 셋팅
        for(int i=0; i<id_list.length;i++) {
            String name = id_list[i];//사용자 ID
           mapIdx.put(name, i); //사용자ID에 대해서 인덱스값과 함께 저장
           map.put(name, new HashSet<>());
        }
cs

 

다음으로 mapIdx는 초기화 작업이 끝났고, map은 value값을 저장할 자료구조로 HashSet을 생성만 했기 때문에 이에 대한 초기화를 마저 하면 다음과 같습니다. 

2. 초기화

1
2
3
4
5
6
7
8
9
10
for(int i=0; i<report.length;i++) {
    String result[] = report[i].split(" ");
    //신고한 사람의 ID
    String a = result[0];
    //신고당한 사람의 ID
    String b = result[1];
    //신고당항 사람의 id와 매핑된 value값에다가 신고한 사람의 id를 추가한다. 
    //단, HashSet의 특성상 중복은 불가능하다. -> 한 사람이 여러번 신고해도 1 count
    map.get(b).add(a);
}
cs
  • report배열에 있는 모든 요소를 한 번씩 순회하면서 공백을 기준으로 문자열을 분리해준다. 
  • 공백 이전의 문자열은 신고한ID이고, 공백 이후의 문자열은 신고당한 ID이다.
  • map에서 신고당한ID를 키값으로 하는 value에 신고한ID를 추가한다. 
  • map에서는 key값이 중복된 상태로 put해버리면 이전 값이 덮어씌워지므로 value값으로 set자료구조를 사용해서 기존값에 add로 추가되어 저장되도록 했다.  

3. 비교

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//map2를 순환
for(int i=0; i<id_list.length;i++) {
    //id_list[i]를 신고한 사람들이 저장되어 있음
    HashSet<String> send = map.get(id_list[i]);
    if(send.size() >= k) { //이용 정지대상이라면
        
        //아까 정한 임의의 인덱스로 id_list에 저장된 id와 같은 순서로 메일통보 횟수 저장
        //위에서 뽑은 send내의 있는 사용자에게 메일을 보내는 횟수를 +1
        for(String name : send) {
            answer[mapIdx.get(name)]++;
            //System.out.print(answer[i]);
        }
    }
}
cs

4번줄을 보면, map에는 id_list에 있는 모든 회원들이 자신을 신고한 사람을 함께 저장하고 있는데 get메소드를 통해 자신을 신고한 사람들인 value값을 HashSet의 자료형으로 반환했습니다. 이 자료구조 내부에 요소들은 String형입니다. 

이 반환값의 크기가 >= k를 만족하는 사용자는 정지 대상자입니다.

개선루프를 사용하여 send에 저장되어 있는 문자열(사용자ID = 정지 대상자)을 초기에 인덱스 값을 저장한 map의 키로 사용하여 얻어낸 value(인덱스)값을 사용하여 배열에 접근하고, 그 해당 요소의 값을 +1 시킵니다.

 

문제 출처 : https://programmers.co.kr/learn/courses/30/lessons/92334