THE DEVLOG

scribbly.

자바스크립트 기본 알고리즘

2023.03.07 23:52:01

먼저 해당 문제는 기다리는 시간이 가장 작은 곳에 사람이 가서 서면 된다.

아래는 최적화를 하지 않은 코드이다.

function solution(n, times) {
    var answer = 0;

    times.sort((a,b)=> a-b)

    const waiting = Array.from(times, (element, idx)=>[0,idx])

    while(n>0) {
        waiting.sort((a,b) => {
            return (a[0]+times[a[1]])-(b[0]+times[b[1]])
        })
        waiting[0][0] += times[waiting[0][1]]
        if(waiting[0][0] > answer) answer = waiting[0][0]
        n -= 1
    }
    
    return answer;
}

한 사람마다 waiting을 정렬하여 가장 기다리는 시간이 적은 곳으로 사람을 배치한다.
당연히 시간 초과가 난다.

해답

"걸리는 시간"을 찾는다.
걸리는 시간은 times[0]과 times.at(-1)*n의 사이에 있을 것이다.
이 사이를 이진탐색으로 순회한다.

function solution(n, times) {
    var answer = 0;

    times.sort((a,b)=> a-b)

    let left = 1
    let right = times[times.length-1]*n
    
    while(left<=right) {
        let mid = Math.floor((left+right)/2)
        let cnt = 0
        
        for(let i=0; i<times.length; i++) {
            cnt += Math.floor(mid/times[i])
            if(cnt >= n) break
        }
        
        if(cnt >= n) {
            answer = mid
            right = mid-1
        } else {
            left = mid+1
        }
    }
    
    return answer;
}
이진 탐색 알고리즘을 사용하여 문제를 해결하는 코드입니다.

우선, times 배열을 오름차순으로 정렬합니다.
이진 탐색을 위한 left와 right 값을 설정합니다. left는 최소 값인 1로, right는 최대 값을 의미하는 times[times.length-1]*n으로 설정합니다.
left가 right보다 작거나 같은 동안 아래 과정을 반복합니다.
mid값을 구합니다. 이진 탐색에서 중간값으로 설정하는 값으로, left와 right의 중간값인 Math.floor((left+right)/2)으로 설정합니다.
cnt 값을 0으로 초기화합니다. cnt는 mid 시간 동안 처리할 수 있는 사람 수를 의미합니다.
for문을 사용하여, times 배열의 값들을 하나씩 확인합니다.
mid 시간 동안, i번째 심사관이 처리할 수 있는 사람 수를 구하고 cnt에 더해줍니다.
cnt가 n 이상이면, mid 시간 내에 n명의 사람들을 모두 처리할 수 있는 것이므로, answer 값을 mid로 설정하고, right 값을 mid-1로 갱신합니다.
cnt가 n 미만이면, mid 시간 내에 n명의 사람들을 처리할 수 없으므로, left 값을 mid+1로 갱신합니다.
left가 right보다 커지면, 이진 탐색을 종료