코테 및 알고리즘

프로그래머스 - 베스트 엘범

Jay_Jung 2024. 7. 17. 12:50

<문제>

https://school.programmers.co.kr/learn/courses/30/lessons/42579

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

<문제 핵심>

1. 해시 자료구조를 사용하는 문제이고 장르별로 총 재생횟수의 합을 저장해놓은 후, 재생 횟수별로 내림차순 정렬을 해놓는 과정이 필요하다. 

✅ Object.entries 메소드를 활용해서 [키, 값] 형태의 배열로 바꿔주고 내림차순 정렬 적용

{classic:1450,pop:3100}

 

2. 고유번호, 장르, 재생횟수가 한데에 모아져있는 객체가 필요하다. 왜냐하면 고유번호에 따라서 장르, 재생횟수를 확인할 수 있기 때문이다.

✅ 각 배열 요소가 {genre: g, index: i, playCnt: plays[i]}로 구성됌

let allInfoObj=genres.map((g,i)=>({
    genre:g,
    index:i,
    playCnt:plays[i]
}))

 

<문제 풀이과정 및 순서도>

1.  장르별로 총 재생횟수의 합을 저장한다. 결과적으로 {classic:1450,pop:3100} 형태가 나올 것이다.

let answer = [];

// 1번 과정
let playCntByGenre={}
for(let i=0;i<genres.length;i++){
    playCntByGenre[genres[i]]=playCntByGenre[genres[i]] ? playCntByGenre[genres[i]]+plays[i] : plays[i]
}

 

2.  많이 재생된 장르의 재생횟수를 기준으로 내림차순 정렬 적용

// 재생횟수로 내림차순 정렬하기 위해, [키,밸류]의 배열 형태로 만들어준다
let keyValueArr=Object.entries(playCntByGenre)
keyValueArr.sort((a,b)=>b[1]-a[1]);

 

3.  고유번호, 장르, 재생횟수가 한데에 모아져있는 객체가 요소인 allInfoObj 배열을 만든다.

let allInfoObj=genres.map((g,i)=>({
    genre:g,
    index:i,
    playCnt:plays[i]
}))

 


4.  각 장르별로 재생 횟수가 많은 상위 두 개의 객체를 찾아서 그 인덱스를 결과 배열에 담는 작업을 수행한다.

✅ keyValueArr 요소에 첫 번째 요소가 장르를 의미하고 해당 장르와 aliiInfoObj의 장르를 비교해서 동일하다면 current 배열에 삽입해준다. 이 또한 재생횟수를 기준으로 내림차순 해줘야하며 2개만 뽑아주기 위해 조건문을 적용한다.

keyValueArr.forEach((k,i)=>{
    let current=[];
    for(let j=0;j<allInfoObj.length;j++){
        if(k[0]===allInfoObj[j].genre){
            current.push(allInfoObj[j]);
        }
    }
    current.sort((a,b)=>b.playCnt-a.playCnt);
    current.forEach((c,i)=>{
        if(i<2){
         // 2개만 뽑아야 하기 때문에 index가 2보다 작을때까지만 answer.push 수행
        answer.push(c.index)
        }        
    })
})

return answer;

 

<전체 코드>

function solution(genres, plays) {
    
    let answer = [];
  
    // 1번 과정
    let playCntByGenre={}
    for(let i=0;i<genres.length;i++){
        playCntByGenre[genres[i]]=playCntByGenre[genres[i]] ? playCntByGenre[genres[i]]+plays[i] : plays[i]
    }
    // 여기서 playCntByGenre는 {classic:1450,pop:3100} 형태
  
    // 재생횟수로 내림차순 정렬하기 위해, [키,밸류]의 배열 형태로 만들어준다
    let keyValueArr=Object.entries(playCntByGenre)
    keyValueArr.sort((a,b)=>b[1]-a[1]);
    // 정렬함수의 compareFunc 작성시, return 값이 양수면 앞뒤순서가 바뀐다는 점을 기억하면 쉽다!
  
    // 여기서 keyValueArr는 [ [ 'pop', 3100 ], [ 'classic', 1450 ] ] 형태
    
    // 2번 과정
    let allInfoObj=genres.map((g,i)=>({
        genre:g,
        index:i,
        playCnt:plays[i]
    })) 
    
    // 3번 과정
    keyValueArr.forEach((k,i)=>{
        let current=[];
        for(let j=0;j<allInfoObj.length;j++){
            if(k[0]===allInfoObj[j].genre){
                current.push(allInfoObj[j]);
            }
        }
        current.sort((a,b)=>b.playCnt-a.playCnt);
        current.forEach((c,i)=>{
            if(i<2){
             // 2개만 뽑아야 하기 때문에 index가 2보다 작을때까지만 answer.push 수행
            answer.push(c.index)
            }        
        })
    })
    
    return answer;
}