평소 식욕이 왕성한 무지는 자신의 재능을 뽐내고 싶어 졌고 고민 끝에 카카오 TV 라이브로 방송을 하기로 마음먹었다. 그냥 먹방을 하면 다른 방송과 차별성이 없기 때문에 무지는 아래와 같이 독특한 방식을 생각해냈다.
회전판에 먹어야 할 N 개의 음식이 있다.
각 음식에는 1부터 N 까지 번호가 붙어있으며, 각 음식을 섭취하는데 일정 시간이 소요된다.
무지는 다음과 같은 방법으로 음식을 섭취한다.
무지가 먹방을 시작한 지 K 초 후에 네트워크 장애로 인해 방송이 잠시 중단되었다.
무지는 네트워크 정상화 후 다시 방송을 이어갈 때, 몇 번 음식부터 섭취해야 하는지를 알고자 한다.
각 음식을 모두 먹는데 필요한 시간이 담겨있는 배열 food_times, 네트워크 장애가 발생한 시간 K 초가 매개변수로 주어질 때 몇 번 음식부터 다시 섭취하면 되는지 return 하도록 solution 함수를 완성하라.
food_times | k | result |
---|---|---|
[3, 1, 2] | 5 | 1 |
처음에는 division hashing을 활용해 k 시간만큼 각 음식을 돌아가면서 1씩 빼는 방법으로 가장 직관적인 방법으로 접근했다. 하지만 이 방법은 O(N * M)
으로 정확성 테스트에서는 충족하나 효율성 테스트는 통과하지 못한다.
두번째 방법으로는 각 음식의 번호를 key, 음식별 먹는데 걸리는 시간을 value로 하는 원소를 가지는 Queue를 활용하는 방법을 떠올렸다. k만큼 offer, poll을 반복하며 1초씩 시간을 빼고, value가 0이면 offer 대상에서 제외하는 방법이다. 하지만 이 방법 역시 처음과 동일한 시간 복잡도를 가지므로 효율성 테스트를 통과하지 못한다. 하지만 풀이 시간이 부족하여 우선 두번째 방법을 선택하여 코드를 작성했으며, 풀이 시간에 1시간 정도가 소요되어 제한 시간을 초과하였다.
또한 프로그래머스의 정확성 테스트에서도 몇개는 통과하지 못했다.
이 해설에서 말하는 제안하는 방법은 k초 안에 먹을 수 있는 음식을 한 번에 제외하는 것
이다.
예를 들어 food_tims가 [8, 6, 4]고 k가 15라고 가정하면 다음과 같이 정리할 수 있다.
(1번 - 8초), (2번 - 6초), (3번 - 4초)
이 음식들 중 k초 안에 먹을 수 있는 음식이 있는지 확인하기 위해서 음식을 먹는데 걸리는 시간 기준으로 정렬
한다.
k = 15초
(3번 - 4초). (2번 - 6초), (1번 - 8초)
음식 하나를 다 먹는데 필요한 시간은 (남은 음식의 개수) * (음식을 먹는데 걸리는 시간)
으로 정의할 수 있다. 그렇다면 3번 음식을 다 먹기 위해서는 남은 음식이 3개, 음식을 먹는데 걸리는 시간 4초로 총 12초가 필요하다. 그리고 나머지 음식들에서 4초씩 빼준다.
k = 3초
(2번 - 2초), (1번 - 4초)
2번 음식을 다 먹기 위해서 필요한 시간은 남은 음식이 2개, 음식을 먹는데 걸리는 시간 2초로 총 4초가 필요하다. 하지만 k의 남은 시간이 3초이므로 2번 음식을 다 먹을 수 없다.
이제 다시 음식의 번호 순대로 정렬
한다.
k = 3초
(1번 - 4초), (2번 - 2초)
3초 후에 어떤 음식을 먹을지는 (남은 음식의 개수) % k + 1
으로 구할 수 있다. 음식 하나를 다 먹기 위해서는 모든 음식을 동일하게 한 번씩 먹기 때문에, 다시 음식을 먹을 때 1번 음식부터 먹는다는 것이 보장되기 때문이다.
이 풀이에서 필요한 자료 구조는 Priority Queue
와 Array List
다. 또한 Food Class를 작성하고 Comparable
을 상속받아 compareTo 메서드를 구현해야 한다.
Priority Queue 정렬은 O(logN)
시간 복잡도를 가지며, Array List 정렬은 O(NlogN)
시간 복잡도를 가진다. 결과적으로 이 풀이는 O(NlogN)
의 시간 복잡도를 가진다.
이 풀이는 효율성 테스트 2번을 제외하고 모두 통과한다. 효율성 테스트 2번이 왜 통과하지 못하는지는 정확히는 모르겠다. 다만 java 기준으로 다른 사람들의 풀이를 검색해보니 이진 탐색을 활용해 풀이하고 있다. 아마 출제자가 의도한 바와 다른 풀이를 활용했기 때문이 아닐까 싶다.
일단 나는 아직 이진 탐색 챕터를 시작하지 않았으므로, 여기에서 만족하고 다음 챕터로 넘어가야겠다.
개발자로서 성장하는 데 큰 도움이 된 글이었습니다. 감사합니다.