코딩 테스트 연습 문제 코딩테스트 연습에 공개된 문제는 (주)그렙이 저작권을 가지고 있습니다.(지문 하단에 별도 저작권 표시 문제 제외)코딩테스트 연습 문제의 지문, 테스트케이스, 풀이 등과 같은 정보는 비상업적, 비영리적 용도로 게시할 수 있습니다.다만 문제의 지문, 풀이 등과 같은 정보를 단순히 게시하는 것을 넘어, 이를 바탕으로 문제를 풀고 채점이 가능하도록 하는 등의 방식으로 활용하는 것은 제한됩니다. ※ 2020 KAKAO BLIND RECRUITMENT, Summer/Winter Coding 등의 문제는 기업 코딩 테스트에 나온 문제이나, 코딩테스트 연습에 공개된 문제이기 때문에 마찬가지로 비상업적, 비영리적 용도로 게시할 수 있습니다. (2021. 01. 08 업데이트)

문제 정보

문제

문제 설명

문제 설명 펼치기/접기

당신은 온라인 게임을 운영하고 있습니다. 같은 시간대에 게임을 이용하는 사람이 m명 늘어날 때마다 서버 1대가 추가로 필요합니다. 어느 시간대의 이용자가 m명 미만이라면, 서버 증설이 필요하지 않습니다. 어느 시간대의 이용자가 n x m명 이상 (n + 1) x m명 미만이라면 최소 n대의 증설된 서버가 운영 중이어야 합니다. 한 번 증설한 서버는 k시간 동안 운영하고 그 이후에는 반납합니다. 예를 들어, k = 5 일 때 10시에 증설한 서버는 10 ~ 15시에만 운영됩니다.

하루 동안 모든 게임 이용자가 게임을 하기 위해 서버를 최소 몇 번 증설해야 하는지 알고 싶습니다. 같은 시간대에 서버를 x대 증설했다면 해당 시간대의 증설 횟수는 x회입니다.

다음은 m = 3, k = 5 일 때의 시간대별 증설된 서버의 수와 증설 횟수 예시입니다.

시각 게임 이용자의 수 증설된 서버의 수 증설 횟수
0 ~ 1 0 0 0
1 ~ 2 2 0 0
2 ~ 3 3 1 1
3 ~ 4 3 1 0
4 ~ 5 1 1 0
5 ~ 6 2 1 0
6 ~ 7 0 1 0
7 ~ 8 0 0 0
8 ~ 9 0 0 0
9 ~ 10 0 0 0
10 ~ 11 4 1 1
11 ~ 12 2 1 0
12 ~ 13 0 1 0
13 ~ 14 6 2 1
14 ~ 15 0 2 0
15 ~ 16 4 1 0
16 ~ 17 2 1 0
17 ~ 18 13 4 3
18 ~ 19 3 3 0
19 ~ 20 5 3 0
20 ~ 21 10 3 0
21 ~ 22 0 3 0
22 ~ 23 1 0 0
23 ~ 24 5 1 1

모든 게임 이용자를 감당하기 위해 최소 7번 서버를 증설해야 하며, 이보다 적은 수의 서버 증설로는 모든 게임 이용자를 감당할 수 없습니다.

0시에서 23시까지의 시간대별 게임 이용자의 수를 나타내는 1차원 정수 배열 players, 서버 한 대로 감당할 수 있는 최대 이용자의 수를 나타내는 정수 m, 서버 한 대가 운영 가능한 시간을 나타내는 정수 k가 주어집니다. 이때, 모든 게임 이용자를 감당하기 위한 최소 서버 증설 횟수를 return 하도록 solution을 완성해 주세요.


제한사항

  • players의 길이 = 24
    • 0 ≤ players의 원소 ≤ 1,000
    • players[i]는 i시 ~ i+1시 사이의 게임 이용자의 수를 나타냅니다.
  • 1 ≤ m ≤ 1,000
  • 1 ≤ k ≤ 24

테스트 케이스 구성 안내

아래는 테스트 케이스 구성을 나타냅니다. 각 그룹 내의 테스트 케이스를 모두 통과하면 해당 그룹에 할당된 점수를 획득할 수 있습니다.

그룹 총점 추가 제한 사항
#1 5% m = 1, k = 1
#2 7% k = 1
#3 88% 추가 제한 사항 없음

입출력 예

players m k result
[0, 2, 3, 3, 1, 2, 0, 0, 0, 0, 4, 2, 0, 6, 0, 4, 2, 13, 3, 5, 10, 0, 1, 5] 3 5 7
[0, 0, 0, 10, 0, 12, 0, 15, 0, 1, 0, 1, 0, 0, 0, 5, 0, 0, 11, 0, 8, 0, 0, 0] 5 1 11
[0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 5, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1] 1 1 12

풀이

풀이 코드

1
2
3
4
5
6
7
8
9
10
11
12
def solution(players, m, k):
    active_servers = [0] * 24 # 시간대별 증설된 서버 수
    count = 0 # 증설 횟수
    for h, player in enumerate(players): # h : hour
        required_servers = player // m # 지금 시점에 필요한 증설 서버 수
        add = max(required_servers - active_servers[h], 0) # 이 시점에 증설할 서버 수
        count += add # 증설 횟수에 추가
        for j in range(k):
            if h + j > 23:
                break
            active_servers[h+j] += add
    return count

풀이 방식

  • 시간대별 증설된 서버 수를 담는 배열을 만들어, 증설 현황과 이력을 볼 수 있게 한다.
  • 각 시간대별로 반복을 수행하며 현재 증설된 서버와 증설되어야 할 서버의 개수를 비교한 뒤 증설한다.

리뷰

점수 리뷰

  • 오랜만에 문제풀이를 하는거라 몸풀 겸 난이도가 높지 않은 문제를 선택했다.
  • 그런데 3점이라니.. 정말 비효율적으로 풀었나보다

개선 포인트

개선해야 할 부분

  1. k번 반복 수행
1
2
3
4
for j in range(k):
    if h + j > 23:
        break
    active_servers[h+j] += add
  • 이 부분은 매 시간대마다 k번 반복을 수행한다.
  • 실제로는 “구간 증가(range add)” 인데, 이를 매번 각 시간을 반복하며 더하고 있는 것이다.
  • 따라서 O(24 $\cdot$ k) 의 시간복잡도를 가진다.
  1. 증설 서버 현황을 실제 값으로 관리함
1
2
3
4
5
6
7
8
active_servers = [0] * 24
...
add = max(required_servers - active_servers[h], 0)
...
for j in range(k):
    if h + j > 23:
        break
    active_servers[h+j] += add
  • 지금 증설한 서버가 앞으로 k시간 동안 영향을 미친다는 사실을 매 시간대마다 미리 계산해 저장하는 방식
문제의 이유 개선점
현재 필요하지 않은 미래의 정보를 미리 계산함 “지금 활성화된” 증설 서버 개수가 몇개인지만 필요
같은 서버 증설 정보가 k번 중복 저장됨 논리적으로는 서버 n대가 h부터 h+k-1까지 유지된다라는 사실만 있으면 됨

개선 방법

  • 누적합 + 차분 배열의 방식으로 개선한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def solution(players, m, k):
    diff = [0] * 25 # 차분 배열 (h+k 처리용)
    active = 0      # 현재 활성화된 증설 서버 수
    count = 0       # 증설 횟수

    for h, player in enumerate(players):
        active += diff[h] # 현재 활성화된 증설 서버 수 업데이트
        required = player // m  # 지금 필요한 증설 서버 수
        add = max(required - active, 0) # 이 시점에 증설할 서버 수

        if add > 0: # 신규 증설 정보가 있을 때에만 수행
            count += add
            active += add # 추가 증설 서버 수 업데이트
            if h + k < 25:
                diff[h+k] -= add # 미래에 종료되는 증설 서버 기록

    return count
  • O(24 $\cdot$ k) 의 시간 복잡도가 O(24)로 개선된다.
  • 증설 서버 현황(active_servers)에서 인덱스로 값을 조회하는 작업이 사라진다.

Comments