다리를 지나는 트럭
1. 개요
프로그래머스
Lv.2
스택/큐
2. 문제 설명
트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 다리에는 트럭이 최대 bridge_length대 올라갈 수 있으며, 다리는 weight 이하까지의 무게를 견딜 수 있습니다. 단, 다리에 완전히 오르지 않은 트럭의 무게는 무시합니다.
예를 들어, 트럭 2대가 올라갈 수 있고 무게를 10kg까지 견디는 다리가 있습니다. 무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다.
0
[]
[]
[7,4,5,6]
1~2
[]
[7]
[4,5,6]
3
[7]
[4]
[5,6]
4
[7]
[4,5]
[6]
5
[7,4]
[5]
[6]
6~7
[7,4,5]
[6]
[]
8
[7,4,5,6]
[]
[]
따라서, 모든 트럭이 다리를 지나려면 최소 8초가 걸립니다.
solution 함수의 매개변수로 다리에 올라갈 수 있는 트럭 수 bridge_length, 다리가 견딜 수 있는 무게 weight, 트럭 별 무게 truck_weights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.
2-1. 문제 설명 - 제한 조건
bridge_length는 1 이상 10,000 이하입니다.
weight는 1 이상 10,000 이하입니다.
truck_weights의 길이는 1 이상 10,000 이하입니다.
모든 트럭의 무게는 1 이상 weight 이하입니다.
2-2. 문제 설명 - 입출력 예
2
10
[7,4,5,6]
8
100
100
[10]
101
100
100
[10,10,10,10,10,10,10,10,10,10]
110
3. 문제 풀이
내가 처음으로 푼 날 것의 풀이이다.
기본적으로 큐(Queue)
자료구조를 사용하였다.
큐에 대한 자세한 내용과 자바스크립트로 큐 자료구조를 구현하는 것은 큐(Queue)에서 확인 가능한다. 기본적인 자료구조에서 다리를 건너고 있는 트럭의 무게를 구하기 위해 this.weight = 0;
를 추가하였고 가장 앞의 노드를 가져오는 second_data()
를 추가하였다.
1) 다리를 지나야하는 트럭의 큐와 다리를 지나고 있는 트럭의 큐 만들기
truck_weights
의 배열을 매개변수로 전달하여 truck_queue
를 만든다.
값이 0이고 길이가 bridge_length
인 배열을 전달하여 bridge_queue
를 만든다. 길이를 bridge_length
로 정한 까닭은 1초에 1만큼의 길이를 갈 수 있기 때문에 하나의 트럭이 다리를 통과하기 위해서는 bridge_length
만큼의 시간이 필요하다. 또한 배열의 요소를 0
으로 채웠다. 만약 트럭이 지나고 있는 위치라면 0
아닌 트럭의 무게 될 것이다.
즉, 다리가 bridge_length
만큼의 칸으로 이루어진 하나의 띠라고 생각하고 1초가 지날 때 마다 한 칸 씩 앞으로 이동한다고 생각하였다.
2) 다리를 지난 트럭 수의 변수와 전체 걸린 시간의 변수 만들기
아래 과정에의 반복문에서 조건에 따라 바꾸게 될 변수를 미리 정한다.
completed_truck
은 다리를 통과한 트럭의 수를 세기 위한 변수이고 total_time
은 반복문이 한 번 실행될 때 마다 1씩 증가한다. 즉, 모든 트럭이 다리를 통과할 때 까지 1씩 증가하게 된다.
3) 다리 위의 맨 앞 트럭을 꺼내오기
dequeue()
를 사용하여 다리의 맨 앞에 있는 트럭을 꺼내욘다. 다리의 길이는 1이 감소된 bridge_length - 1
이 된다. 아래에서 다시 enqueue()
를 통해 다리를 길이를 bridge_length
로 만들어준다.
4) 꺼낸 트럭의 값이 0이 아니라면 completed_truck를 1 증가시키기
만약 꺼낸 트럭의 값이 0이 아니라는 것은 트럭의 무게 이므로 트럭이 다리를 건넜다는 것이다. 그렇기 때문에 completed_truck
의 값을 1 증가시켜야 한다.
5) 만약 다리를 지난 트럭의 수가 전체 트럭의 수와 같다면 현재의 시간을 리턴하기
다리를 지난 트럭의 수를 나타내는 변수 completed_truck
의 값이 트럭의 무게를 요소로 가진 truck_weights
배열의 길이와 같아지는 시점이라면 해당 시점이 모든 트럭이 다리를 모두 통과한 시간이다. 그러므로 total_time
를 리턴한다.
6) 다음으로 다리를 건너게 될 트럭을 꺼내오기
truck_queue
에서 맨 앞의 값을 가져온다. 위 코드에서는 second_data()
함수를 만들어 가져왔지만 굳이 이러지 않고 아래와 같이 가져올 수도 있다.
7) 현재 다리 위의 트럭의 무게와 다음 차례 트럭의 무게를 합 한 값과 다리가 견딜 수 있는 무게 비교하기
다음 차례의 트럭의 무게까지 다르가 견딜 수 있다면 해당 트럭을 truck_queue
에서 꺼내 bridge_queue
에 넣는다. 만약 그렇기 않는다면 bridge_queue
에는 0를 넣는다.
이런 반복문을 통해 truck_queue
에서 bridge_queue
로 차례차례 트럭이 이동하게 된다.
결과
4. Refactoring
굳이 큐 자료구조를 사용하지 않아도 되어 리팩토링에서는 truck_weights
를 가지고 큐를 만들지 않았다. 그 외의 과정은 순서만 약간 다를 뿐 똑같다고 봐도 무방하다.
단 하나더 만약 truck_weights
의 길이가 i
보다 작아졌다는 것은 더 이상 출발 대기 중인 트럭이 없다는 뜻이고 바로 직전에 마지막 트럭이 다리 위로 올라갔다는 것이다. 그렇기 때문에 time
에 다리의 길이인 bridge_length
를 더한 값을 리턴해야 한다.
결과
5. 다른 사람 풀이
문제 설명이 잘 되어 있는 풀이를 가져왔다. 아래의 풀이는 큐 자료구조를 사용하지 않고 배열을 사용하고 문제를 풀고 있어 Array.shift()
메서드를 사요하고 있다. 배열의 길이가 만 이하라면 굳이 큐 자료구조를 사용하지 않고 Array.shift()
를 사용해도 괜찮은 듯 하다. 오히려 시간이 더 단축 된 것이 신기할 따름이다.
아무래도 나의 풀이와 리팩토링에서는 큐 자료구조를 생성할 때 반복문을 사용하여 이미 시간 복잡도 O(n)
를 가지고 있어 비슷한 시간이지 않을까 하는 생각이 든다. 그래도 큐에 대해 공부할 수 있는 시간과 굳이 큐를 사용하지 않고 배열을 통해 문제를 해결할 수 있는 시간을 가져 좋은 문제 풀이였다고 생각한다.
마지막으로 다리에 트럭이 추가될 수 없는 경우 시간을 점프한다는 것과 트럭이 나갈 시간을 기존 까지 흐름 시간을 더해 관리한 것이 멋지게 느껴졌다.
결과
6. Conclusion
문제를 풀 때 실수를 많이 해서 시간이 오래 걸렸다. 어떤 방법으로 풀어야 할지에 대한 감을 이미 잡혔지만 변수명을 헷갈리는 문제와 더불어 큐의 자료를 가져와 더하는 과정에서 잘못된 데이터를 사용하여 값이 이상해는 경우가 있었다. 또한
while
문의 조건을 명확히 하지 않아 루프를 빠져나오지 못하는 경우도 생겼다. 아직 꼼꼼하지 못한 것 같아 더 노력을 해야 할 듯 하다. 천천히 하지만 확실히 한 번에 해결 할 수 있도록!
📅 2022-09-17
Last updated