문제
https://programmers.co.kr/learn/courses/30/lessons/42583
풀이
문제를 처음 읽었을 당시 실제로 큐에 값이
차례로 Insert / POP 되는 형태보다
weight를 넘지 않는 인접값끼리 한 꺼번에
처리하면 좋지 않을까 하며 그림을 그려봤다.
truck_weights : [7, 4, 5, 1, 6]
bridge_length : 3
weight : 10
--------------------------------
7 | 4, 5, 1 | 6
(3+0) + (3+2) + (3+0) = 11
한 번에 건널 수 있는 트럭의 개수를 나누고
길이 + (트럭수-1)로 값을 뽑아내서 더해보니
그럴듯 한 답이 나왔다.
그래서 바로 시도해봤던 코드
def solution(bridge_length, weight, truck_weights):
Q = []
for tw in truck_weights :
if len(Q)==0 or Q[-1][0]+tw > weight :
Q.append([tw, 1])
else :
Q[-1][0] += tw
Q[-1][1] += 1
return sum((q[1]-1)+bridge_length for q in Q)
이전 포스팅에서 배웠던 빈 Q를 알아내는 방법이나,
Q를 해시처럼 이용한 것은 좋았으나, 정답이 아니었다.
어떡하나 고민해보다가, 쉽게 시도했을 때 해결되는 사례도 있었기 때문에
이번에도 쉬운 방법으로 시도해봤다.
def solution(bridge_length, weight, truck_weights):
bridge = [0 for i in range(bridge_length)]
sec = 0
while bridge:
sec += 1
bridge.pop(0)
if truck_weights:
if sum(bridge)+truck_weights[0] <= weight:
bridge.append(truck_weights.pop(0))
else:
bridge.append(0)
return sec
성공이네?
그런데 역시 걱정한대로 속도가 어마무시하다…
테스트 1 〉 통과 (13.05ms, 10.2MB)
테스트 2 〉 통과 (1501.33ms, 10.3MB)
테스트 3 〉 통과 (0.03ms, 10.3MB)
테스트 4 〉 통과 (335.04ms, 10.4MB)
테스트 5 〉 통과 (9623.82ms, 10.2MB)
테스트 6 〉 통과 (1569.48ms, 10.2MB)
.
.
.
특히 테스트 5번의 경우 9.6초…
프로그래머스 채점 제한시간인 10초에 걸릴 뻔 했다.
pop(0) 함수가 맨 좌측의 요소를 제거하고
뒤 값들을 한 칸씩 당겨오기 떄문에
시간을 잡아먹는 주범이라길레
Deque도 사용해보고 Queue를 reverse도 시켜봤으나
별다른 차이를 보여주지 못했다.
아무리 생각해도 좋은 풀이는 아니었다.
더 나은 풀이를 찾아봐야겠다.
더 나은 풀이
import collections
DUMMY_TRUCK = 0
class Bridge(object):
def __init__(self, length, weight):
self._max_length = length
self._max_weight = weight
self._queue = collections.deque()
self._current_weight = 0
def push(self, truck):
next_weight = self._current_weight + truck
if next_weight <= self._max_weight and len(self._queue) < self._max_length:
self._queue.append(truck)
self._current_weight = next_weight
return True
else:
return False
def pop(self):
item = self._queue.popleft()
self._current_weight -= item
return item
def __len__(self):
return len(self._queue)
def __repr__(self):
return 'Bridge({}/{} : [{}])'.format(self._current_weight, self._max_weight, list(self._queue))
def solution(bridge_length, weight, truck_weights):
bridge = Bridge(bridge_length, weight)
trucks = collections.deque(w for w in truck_weights)
for _ in range(bridge_length):
bridge.push(DUMMY_TRUCK)
count = 0
while trucks:
bridge.pop()
if bridge.push(trucks[0]):
trucks.popleft()
else:
bridge.push(DUMMY_TRUCK)
count += 1
while bridge:
bridge.pop()
count += 1
return count
def main():
print(solution(2, 10, [7, 4, 5, 6]), 8)
print(solution(100, 100, [10]), 101)
print(solution(100, 100, [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]), 110)
if __name__ == '__main__':
main()
Bridge 클래스를 직접 작성해서 풀어낸 코드
‘이렇게 짤거면 C++ 이나 Java가 낫지 않나?’
라는 생각이 많이 들어서, 개인적으로는 잘 모르겠다.
아마 Deque을 이용하고, if문 조건을 최대한 깔끔하게 설정해서
Deque에 변화가 일어나는 것을 최소한으로 막았기 때문에
속도는 빠른지 않을까 예상해본다.
댓글남기기