코딩테스트

[코딩테스트] 2022 KAKAO BLIND RECRUITMENT 신고 결과 받기(Javascript)

보오 2022. 2. 6. 15:11

문제 보러 가기: https://programmers.co.kr/learn/courses/30/lessons/92334

 

코딩테스트 연습 - 신고 결과 받기

문제 설명 신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의

programmers.co.kr

 

<나의 풀이>

function solution(id_list, report, k) {
    var answer = Array.from({length: id_list.length}, ()=>0);
    var report_map = new Map(); // 신고 명단
    id_list.forEach((id)=>{
        report_map.set(id, []); // 신고 명단 초기화(각 id마다 빈 배열을 할당)
    })
    var report_count = new Map(); // 피신고자 누적 횟수
    var report_set = new Set(report);

    report_set.forEach((re)=>{
        var [reporter, reported] = re.split(" ");
        // 신고 명단 작성
        report_map.set(reporter, [...report_map.get(reporter), reported]);
        // 피신고자 누적 횟수 계산
        if(report_count.has(reported)) report_count.set(reported, report_count.get(reported) + 1);
        else report_count.set(reported, 1);
    })

    const reported_list = Array.from(report_map.values());

    report_count.forEach((value, key)=>{
        if(value >= k) {
            reported_list.forEach((list, index)=>{
                if(list.includes(key)) answer[index] = answer[index] + 1;
            })
        }
    })

    return answer;
}

 

<해설>

이 문제를 풀기 위해서는 누가 누구를 신고했는지에 대한 "신고 명단"과, 누가 몇번 신고 당했는지에 대한 "피신고 누적 횟수"가 필요하다.
전자는 각 유저의 신고 명단에 최종 신고 처리된 사람들이 있다면 카운트해주기 위함이고, 후자는 각 유저별로 신고 당한 횟수가 k번을 넘었는지 알기 위함이다.

 

<사용 알고리즘>

Javascript Map, Set 자료형
Map, Set의 개념만 알고 있다면 두 개를 활용해서 충분히 풀 수 있는 문제다.

 

1. answer는 id_list의 갯수만큼 각 원소가 0으로 초기화된 배열로 만들어준다. (Array.from 이용)

    구하고자 하는 값이 각 유저 별 최종 신고 완료 메일을 받은 횟수를 구하는 것이기 때문이다.

2. id_list의 순서대로 report_map을 빈 배열로 초기화 해준다.

    이렇게 한 이유는 추후에 map의 value만을 가지고 최종 신고 처리된 사람들이 있다면 그 누적 값을 answer 배열에서 같은 index을 찾아서 바로 넣어주기 위함이다.

3. 피신고 누적 횟수를 구하기 위해 report_count을 Map 객체로 만든다.

4. report 배열로 신고 명단을 만드는데, 그 전에 ** 중복 신고 무효처리를 위해 Set을 이용, report 원본 배열에서 중복 제거를 해준다.

    ex) "muzi prodo", "muzi prodo" 는 무지가 프로도를 2번이나 신고한 것이기 때문에 1번으로 친다.

5. 중복 제거된 report_set 배열을 forEach loop로 돌려서 신고명단을 작성함과 동시에, 피신고 횟수를 누적한다. (불필요한 for문의 반복을 피하기 위함)

6. 신고 명단(report_map)의 value만을 가져다가 id_list로 정렬된 신고 명단(reported_list) 배열을 구한다. (map.prototype.values 이용)

7. 누적 횟수 배열을 forEach loop을 돌려 k번 이상 신고된 유저가 있다면, reported_list에 해당 유저가 들어있는지 구한 후(array.prototype.includes 이용) 있다면 answer의 index번째 값에 1을 더한다.

 

<총평>

처음에 중복 제거하는 것을 깜빡하여 테스트 문제 2번을 틀렸었다. 중복 제거 로직만 잘 끼워넣으면 풀기에는 무난하다. Map, Set의 개념을 확실히 아는 것이 중요하다. 6~7번 과정은 좀 더 직관적이고 단순하게 할 수 있을 것 같은데 더 생각해봐야겠다.

 

p.s. 괜찮은 방법이 있다면 댓글로 공유 부탁드립니다~