본문 바로가기
이직준비/Algorithm

[Algorithm] 카카오2022 - 신고 결과 받기

by Geunny 2022. 3. 2.
반응형

카카오 2022년 Level 1 (프로그래머스 기준) 문제이다.

 

http://https://programmers.co.kr/learn/courses/30/lessons/92334

 

문제풀이 방법으로 처음 생각했던 방식이다.

 

이름별로 신고한 이름을 리스트로 만들고

이름이 리스트에 존재하지 않을때만 신고한 이름을 추가한다.

(중복신고 불가능하기 때문)

 

이후 리스트에 추가 되면 해당 이름의 신고 카운트를 1 증가시킨다.

 

처음 작성한 코드

 

import java.util.*;
import java.util.stream.Collectors;
class Solution {
    public int[] solution(String[] id_list, String[] reports, int k) {
        int[] answer = new int[id_list.length];
        Map<String,List<String>> userList = new LinkedHashMap<String, List<String>>();
        Map<String, Integer> reportsCount = new HashMap<String, Integer>();
        
        for(String id : id_list){
            userList.put(id,new ArrayList<String>());
            reportsCount.put(id, 0);
        }
        
        for(String report : reports){
            String[] split = report.split(" ");
            List<String> list = userList.get(split[0]);
            if(!list.contains(split[1])){
                userList.get(split[0]).add(split[1]);    
                reportsCount.put(split[1], reportsCount.get(split[1]) + 1);
            }
        }
        for(int idx = 0; idx < userList.values().size(); idx++){
            List<String> data = userList.values().stream().collect(Collectors.toList()).get(idx);
            for(String s : data){
                if(reportsCount.get(s) >= k){
                    answer[idx]++;
                }
            }
        }

        return answer;
    }
}

 

위 소스로도 테스트는 통과가 된다.

하지만 많이 더러움을 느낀다.

 

객체지향을 지향하기 위해 객체지향적으로 해당 코드를 리펙토링 해보겠다.

 

 

리팩토링 과정

 

1. 먼저 'Map<String,List<String>>' 너무 지저분하다.

이를 깔끔하게 바꾸기 위해 이름과 리스트를 갖고 있는 객체로 바꿔준다.

 

MapMap<String,List<String>> userList = new LinkedHashMap<String, List<String>>();
// ==>
class User{
	String name;
    List<String> list;
    public User(String name, List list){
    	this.name = name;
        this.list = list;
    }
}
...

List<User> userList = new ArrayList<>();

for(String id : id_list){
    userList.add(new User(id, new ArrayList<String>()));
    reportsCount.put(id, 0);
}

초기화 또한 위처럼 새로운 객체를 생성하면서 유저리스트에 추가해준다.

 

여기서 또하나.

유저가 신고된 횟수를 굳이 따로 저장하지 않고 User 객체 안에

해당 아이디의 신고횟수도 넣어준다.

 

class User{
	String name;
    List<String> list;
    int reportCount;
    public User(String name, List list){
    	this.name = name;
        this.list = list;
    }
}

신고 카운트는 따로 할당해 주지 않아 0으로 초기화 된다.

 

이로써 위의 초기화 코드가 아래같이 간결해 진다.

 

 

for(String id : id_list){
    userList.add(new User(id, new ArrayList<String>()));
    // reportsCount.put(id, 0); 필요없어짐
}

 

다음은 신고 문자열에 대한 처리이다.

 

        for(String report : reports){
            String[] split = report.split(" ");
            String name = split[0];
            String target = split[1];
            List list = userList.stream()
                    .filter(v -> name.equals(v.name))
                    .findFirst()
                    .get().list;

            if(!list.contains(target)){
                list.add(target);
                userList.stream()
                        .filter(v -> target.equals(v.name))
                        .findFirst()
                        .get().addCount();
            }
        }
        
        class User{
            String name;
            List<String> list;
            int reportCount;
           ...

            public void addCount(){
                this.reportCount++;
            }
         }

소스가 더 더러워진것 같지만... 일단 나중에 다시 정리해 볼까한다.

addCount 는 User 객체에서 자신의 신고카운터를 +1 하는 메서드로 정의했다.

 

다음은 이제 해당 유저가 신고한 유저들 가운데 신고카운터(k) 를 넘는 횟수를 확인하여

배열에 신고된 유저수를 넣어준다.

 

        for(int idx = 0; idx < userList.size(); idx++){
            User user = userList.get(idx);
            List<String> reportList = user.list;
            for(String report : reportList){
                int count = userList.stream()
                        .filter(v -> report.equals(v.name))
                        .findFirst().get().reportCount;
                if(count >= k){
                    answer[idx]++;
                }
            }
        }

 더 더러워져 진것 같다...

 

 

최종코드

 

class Solution {
    public int[] solution(String[] id_list, String[] reports, int k) {
        int[] answer = new int[id_list.length];
        List<User> userList = new ArrayList<User>();
        // Map<String, Integer> reportsCount = new HashMap<String, Integer>();

        for(String id : id_list){
            userList.add(new User(id, new ArrayList<String>()));
        }

        for(String report : reports){
            String[] split = report.split(" ");
            String name = split[0];
            String target = split[1];
            List list = userList.stream()
                    .filter(v -> name.equals(v.name))
                    .findFirst()
                    .get().list;

            if(!list.contains(target)){
                list.add(target);
                userList.stream()
                        .filter(v -> target.equals(v.name))
                        .findFirst()
                        .get().addCount();
            }
        }

        for(int idx = 0; idx < userList.size(); idx++){
            User user = userList.get(idx);
            List<String> reportList = user.list;
            for(String report : reportList){
                int count = userList.stream()
                        .filter(v -> report.equals(v.name))
                        .findFirst().get().reportCount;
                if(count >= k){
                    answer[idx]++;
                }
            }
        }

        return answer;
    }
}

댓글