프로그래머스 - [Level 4] 무지의 먹방 라이브(JAVASCRIPT)

1 minute read

프로그래머스 무지의 먹방 라이브[2019 카카오 블라인드]

카테고리 : 시뮬레이션

전형적인 시뮬레이션 문제다. 배열의 shift() 시간복잡도를 생각못하고
애먹었던 문제였다.

풀이과정은 아래와 같다.
핵심적인 아이디어는
"k(초) - (가장 작은 음식의 양 * 현재 남은 음식의 갯수)"
k 값을 제거해나가는 것이다. 

이때, 매번 모든 음식의 양은 가장 작은 음식의 양씩 줄어들기 때문에 
(실제로 로테이션을 돈것이나 마찬가지이기에)
 음식값을 누적해 계산해줘야한다.

----------------------------------------------------
[5 7 8 2 3 3 3 2]  초기 food_times배열이라면
가장 최소 음식의 양인 2 기준으로 한번의 로테이션을 돌면
[3 5 6 0 1 1 1 0]  된것이나 마찬가지라고 생각하면 된다.
----------------------------------------------------

따라서, 다시 식을 정리하면

"k(초) - (가장 작은 음식의 양 - 현재 누적된 음식의 양) * (현재 남은 음식의 갯수)"
 된다.

k의 값이 현재 남은 음식의 갯수보다 작을 때까지 무한반복한다.

이후 반복문을 빠져나오면 음식의 양이 0 음식은 제거해주고
배열의 k+1 번째 값의 index를 리턴하면 답이된다.


1) 큐에 [food_time,index] 형식으로
food_time을 기준으로 오름차순 정렬해 food_times의 원소를 넣어준다.

2) k  값을 제거해나간다.
idx : 현재 위치
count : 누적 음식 
sum : 현재(idx) 음식의  - 누적 음식 
queue.length-idx : 현재 남은 음식의 갯수

* k() 제거해준다.

k - = (queue.length - idx) * sum;

* 다먹어 치운 음식은 0 으로 만들어준다.
이때, queue를 shift() 해주면 시간초과가 발생한다.
배열의 삭제(shift()) 최악일 , O(N) 시간복잡도가 발생하기때문이다.
따라서 queue.shift() 아닌 idx를 활용해 queue[idx][0]=0 으로 치환해주며,
문제를 풀이해야한다.

if(queue[idx][0]-count===0){
	queue[idx][0]=0;
	idx++;
}

3) 음식의 값이 0이면 제거해주고 인덱스 순으로 정렬해준다.
이때 큐의 k+1 번째 값의 인덱스를 리턴하면 답이 된다.


소스 코드

function solution(food_times, k) {
    let count=0;
    let queue=food_times.map((a,b)=>[a,b]).sort((a,b)=>a[0]-b[0]);
    const total = food_times.reduce((a,b)=>{return a+b},0);
    if(total<=k) return -1;
    
    let idx=0;
    while(queue.length-idx){
        let sum=queue[idx][0]-count;
        if(k-(queue.length-idx)<0) break;
        while(k-(queue.length-idx)*sum<0)
            sum--;
        
        k-=(queue.length-idx)*sum;
        count+=sum;
        while(true){
            if(queue[idx][0]-count===0){
                queue[idx][0]=0;
                idx++;
            }else{
                break;
            }
        } 
    }
    queue=queue.filter((a,b)=>a[0]>0).sort((a,b)=>a[1]-b[1]);
    return queue[k][1]+1;
}


Leave a comment