성능 요약
- 메모리: 77.2 MB, 시간: 0.09 ms
구분
- 코딩테스트 연습 > 스택/큐
Answer Code1(23.04.03)
/**
* bridge_length : 다리에 올라갈 수 있는 트럭 수
* weight : 다리가 견딜 수 있는 무게
* truck_weights : 트럭 별 무게
*/
import java.util.*;
class Solution {
public int solution(int bridge_length, int weight, int[] truck_weights) {
Queue<Integer> queue = new LinkedList<>();
int sum = 0; // 현재 다리를 건너는 트럭 무게의 합
int time = 0; // 모든 트럭이 다리를 건너는 최소의 시간
for(int i = 0; i < truck_weights.length; i++) { // 향상된 for문을 쓰는게 좋을 것
int truck = truck_weights[i];
while(true) {
// [1] 큐가 비어있는 경우 = 어떠한 트럭도 다리위에 없는 경우
if(queue.isEmpty()) {
queue.add(truck);
sum += truck;
time++; // 다리에 오를 때만 시간 추가
break;
} else if(queue.size() == bridge_length) { // [2] 큐가 가득찬 경우
sum -= queue.poll();
} else { // [3] 큐가 다리 길이만큼 가득 차지 않는 경우
// weight 값을 넘지 않는 선에서 새로운 트럭을 다리에 올려줌
if(sum + truck <= weight) {
queue.add(truck);
sum += truck;
time++;
break;
} else {
// weight 값을 넘는다면, 0을 넣어 이미 큐에 있는 트럭이 다리를 건너게 만듬
queue.add(0);
time++;
}
}
}
}
// 마지막 트럭에서 반복문이 끝나는데, 마지막 역시 다리 길이만큼 지나가야 하기 때문에, 다리 길이만큼 더해준다.
return time + bridge_length;
}
}
문제 풀이 - Answer Code1
-
트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 한다. =>
큐
를 사용한다. -
큐를 다리라고 생각하고, 조건에 맞게 트럭을 큐에 넣고 빼면서 최소 몇 초가 걸리는 지 return 하면 되는 문제였다.
-
고려해야할 사항
-
다리에는 트럭이 최대
bridge_length
대 올라갈 수 있고, 다리는weight
이하까지의 무게를 견딜 수 있다. -
다리에 완전히 오르지 않는 트럭의 무게는 무시한다 == 다리를 건너는 트럭의 무게만 측정한다 => 같은 의미.
-
트럭이 다리에 올라가면 1초가 시작되고, 다리 위에서 1칸씩 움직일 때마다 역시 1초가 흘러간다.
-
-
다리에 트럭을 넣는 조건은 총 3가지다.
-
[1] 큐가 비어있는 경우 -> 트럭을 다리에 올려준다 (시간은 +1 증가)
-
[2] 큐가 가득찬 경우 -> 이때는 가장 앞에 넣은 트럭이 다리의 끝에 도달했다는 의미이므로 poll() 메서드를 이용해 트럭을 꺼내 줌으로써, 다리를 건너가도록 한다. 이때 다리에서 내릴 때는 시간이 들지 않는다.
-
[3] 큐가 다리 길이만큼 가득 차지 않는 경우 -> 큐에 이미 있는 트럭에 다리를 지나갈 수 있도록 0 값을 넣어준다. (시간은 +1 증가)
-
-
이 과정을 전체 트럭의 개수만큼 반복한다.
-
위의 반복문의 특성상 마지막 트럭의 경우 다리에는 올랐지만 다 건너지는 못한다. 그래서 정답을 출력할 때는 지금까지 걸린 time에서 마지막 트럭이 건너는데 걸리는 시간인
다리의 길이
를 더해서 출력하면 된다.
Answer Code2(23.12.18)
// 다리를 지나는 트럭(23.12.18) - 1차 복습
import java.util.*;
class Solution {
public int solution(int bridge_length, int weight, int[] truck_weights) {
int sum = 0; // 현재 다리를 지나는 트럭 무게의 합
int time = 0; // 모든 트럭이 다리를 건너는 최소 시간의 합(걸린 시간)
Queue<Integer> bridgeQueue = new LinkedList<>(); // 다리를 지나기 전 트럭
for(int truck : truck_weights) {
while(true) {
// 1. 큐가 비어있는 경우 트럭 추가
if(bridgeQueue.isEmpty()) {
bridgeQueue.offer(truck);
sum += truck;
time++; // 다리에 오를 때만 시간 추가
break;
}
// 2. 다리에 건너는 트럭 무게의 합 == 견딜 수 있는 최대무게(weight)
else if(bridgeQueue.size() == bridge_length) {
sum -= bridgeQueue.poll();
}
// 3. 큐가 비어있지 않은 경우
else {
// 2-2. (다음 트럭까지 포함하여) 다리에 건너는 트럭 무게의 합 > 견딜 수 있는 최대 무게
if(sum + truck > weight) {
bridgeQueue.offer(0);
time++;
}
// 2-3. (다음 트럭까지 포함하여) 다리에 건너는 트럭 무게의 합 < 견딜 수 있는 최대 무게
else {
bridgeQueue.offer(truck);
sum += truck;
time++;
break;
}
}
}
}
// 걸린 시간 + 마지막 트럭의 통과 시간
return time + bridge_length;
}
}
Review
-
큐를 이용해서 문제를 풀어야 겠다는 생각은 가졌지만, 경우의 수를 생각하는 데 있어서 어려움이 있었다.
-
단순히 머리로만 생각하지말고, 뭔가 생각할 게 많다고 생각하면 그림을 그리면서 풀어가는 습관을 가지도록 하자.