본문 바로가기

문과 코린이의, [알고리즘] 기록

[문과 코린이의 IT 기록장] JS(Javascript) 프로그래머스(Programmers) 코딩 테스트 - 신고 결과 받기

반응형

[문과 코린이의 IT 기록장] JS(Javascript) 프로그래머스(Programmers) 코딩 테스트 - 신고 결과 받기

[문과 코린이의 IT 기록장] JS(Javascript)  프로그래머스(Programmers) 코딩 테스트 - 신고 결과 받기 

 


 

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

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

programmers.co.kr


[ 풀이 1 ]

function solution(id_list, report, k) {
    // report 중복 제거
    const set = new Set(report); // 중복값이 있는 배열을 Set객체로 만들어, 중복 제거 후
    const newReport = [...set]; // 전개연산자를 통해, 다시 배열로 변환함. (Spread Operator)
    // var는 변수 재선언 가능, 재할당 가능. 
    // let은 변수 재선언 불가능, 재할당 가능. 
    // const는 변수 재선언 불가능, 재할당 불가능. (그러나 배열 각각에 값 변경은 가능. push로 추가도 가능. 재할당만 불가능한 것)
    const out = []; // 정지 id // 배열 생성 (빈 배열 개수 제한 X)
    const count = Array(id_list.length).fill(0); // 신고 당한 수 [0,0,0,0] // count 배열
    const mail = Array(id_list.length).fill(0); // 메일 받는 수[0,0,0,0] // mail 배열
    
    
    // 신고 당한 횟수 정리 코드
    // for문에서 var로 변수를 선언할 경우, for문 밖에서도 변수 참조가 가능하다. (i++를 통해 4번까지 돌린 후, 나와서 i=5 출력 가능)
    // 그러나 for문에서 let변수를 선언하게 되면, for문 밖(블록 밖)에서는 변수 참조가 불가능함.
    for(let i of newReport){
        let uId = i.split(" ")[0]; // 유저 ID
        let rId = i.split(" ")[1]; // 유저가 신고한 ID
        
        let idx_rId = id_list.indexOf(rId); // id_list에서 신고받은 유저의 index 찾기
        count[idx_rId] += 1; // count배열에, 해당 유저 신고 횟수 누적시키기
        
        // 특정 유저의 신고당한 횟수가 k보다 많다면
        if(count[idx_rId] >= k){
            out.push(id_list[idx_rId]); // 정지 리스트에 해당 아이디 추가
        }
    }
    
    
    // 메일 수신 개수 정리 코드
    for(let i of newReport){
        let uId = i.split(" ")[0]; // 유저 ID
        let rId = i.split(" ")[1]; // 유저가 신고한 ID
        
        // 신고한 ID중 정지된 ID가 있는지 확인하기
        if(out.indexOf(rId) >= 0) {
            let idx_uId = id_list.indexOf(uId);
            mail[idx_uId] += 1;
        }
    }
    
    
    return mail
}

 

* 참고 - var / let / const

var : 변수 재선언 가능, 재할당 가능. 
let : 변수 재선언 불가능, 재할당 가능. 
const : 변수 재선언 불가능, 재할당 불가능. (그러나 배열 각각에 값 변경은 가능. push로 추가도 가능. 재할당만 불가능한 것)


[ 풀이 2 ]

function solution(id_list, report, k) {
    // map함수는 객체를 직접 사용하거나 변형시키지 않지만, callbackfn을 통해 수정 가능하다. (그러나 문제 발생 가능)
    // report배열을 Set객체로 만들어 중복 제거 후, 전개연산자를 통해 다시 배열로 변환한다.
    // 이후, 해당 배열 {"a b"}를 공백 기준으로 나누어 newReport에 추가한다. => {{a},{b}} 형태로 만들어진 것.
    let newReport = [...new Set(report)].map(a=>{return a.split(' ')});

    
    
    // 맵 객체 메소드 : 기존 객체와는 다르게, 메소드만을 넣고 뺀다. 
    // map은 키-값 쌍의 자료구조이다.
    // * 가능한 메소드 : set() - 객체 삽입 , 이차원 배열, get() - 객체 조회, delete() - 객체 삭제, clear() - 맵 안의 전체 프로퍼티 삭제
    let counts = new Map(); // counts : 신고당한 횟수
    for(const bad of newReport){
        // map객체.set(key, value) : 해당 맵에 key-value값을 집어넣음
        // counts.get(bad[1]) : bad[1]에 해당하는 value값이 없으면 undefined = 0 반환
        // ||연산자 사용 방식 => a(문자열이면 1) || 1 : 둘 다 true(1)이면 왼쪽 값 반환, 왼쪽이 false(문자열이 아니면)이면 오른쪽 값 true(1)반환
        // 따라서 bad[1]이 처음으로 신고당한 것이라면, 왼쪽 값 1(undefined+1)을 리턴할 것이고, 신고당한적이 있으면 +1(bad[1]의 value값 + 1)해서 왼쪽 값 리턴할 것임
        counts.set(bad[1], counts.get(bad[1])+1||1)
    }
    
    let good = new Map(); // good : 정지시킨 사람 id
    for(const report of newReport){
        if(counts.get(report[1]) >= k){ // report[1]의 신고당한 횟수가 k회 이상이면(report[1]이 정지되었다면)
            good.set(report[0], good.get(report[0])+1||1) // report[0]의 신고 횟수를 증가시킨다. (report[0], 정지시킨 횟수)
        }
    }
    
    let answer = id_list.map(a=>good.get(a)||0) // answer : 메일 받은 횟수 (정지시킨 횟수)
    // 해당 id_list를 good map 객체에서 찾는다. 
    // 해당 id가 정지시킨 횟수가 0이라면 0을 return할 것이고, 1 이상이면 해당 값을 return해서 answer에 넣을 것이다.
    
    return answer;
    
}

 

* 참고 : javascript에서 map

1. Array.prototype.map() : 특정 배열 내 모든 요소에 대해, 각각 함수를 적용하고, 이 결과를 모아 새로운 배열 반환

    // map함수는 객체를 직접 사용하거나 변형시키지 않지만, callbackfn을 통해 수정 가능하다. (그러나 문제 발생 가능)
    // report배열을 Set객체로 만들어 중복 제거 후, 전개연산자를 통해 다시 배열로 변환한다.
    // 이후, 해당 배열 {"a b"}를 공백 기준으로 나누어 newReport에 추가한다. => {{a},{b}} 형태로 만들어진 것.
    let newReport = [...new Set(report)].map(a=>{return a.split(' ')});

2. Map() : Java의 HashMap, Python의 dictionary와 같은 {key:value}로 이루어진 자료구조

 // 맵 객체 메소드 : 기존 객체와는 다르게, 메소드만을 넣고 뺀다. 
    // map은 키-값 쌍의 자료구조이다.
    // * 가능한 메소드 : set() - 객체 삽입 , 이차원 배열, get() - 객체 조회, delete() - 객체 삭제, clear() - 맵 안의 전체 프로퍼티 삭제
    let counts = new Map(); // counts : 신고당한 횟수
    for(const bad of newReport){
        // map객체.set(key, value) : 해당 맵에 key-value값을 집어넣음
        // counts.get(bad[1]) : bad[1]에 해당하는 value값이 없으면 undefined = 0 반환
        // ||연산자 사용 방식 => a(문자열이면 1) || 1 : 둘 다 true(1)이면 왼쪽 값 반환, 왼쪽이 false(문자열이 아니면)이면 오른쪽 값 true(1)반환
        // 따라서 bad[1]이 처음으로 신고당한 것이라면, 왼쪽 값 1(undefined+1)을 리턴할 것이고, 신고당한적이 있으면 +1(bad[1]의 value값 + 1)해서 왼쪽 값 리턴할 것임
        counts.set(bad[1], counts.get(bad[1])+1||1)
    }

 


* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)
반응형