ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다리를 지나는 트럭
    알고리즘 2021. 9. 13. 19:55

    내 풀이법

    문제해석

    • 트럭들이 다리를 지나가는데 걸리는 시간을 구하라
    • 트럭들은 1초마다 다리의 길이의 1씩 지나간다
    • 다리에는 무게제한이 있다 (weight)

     

    내가 생각한 풀이법

    • 특별한 이벤트 발생할 때와 지속적으로 발생하는 이벤트를 나눠서 코드를 작성함
    • 특별한 이벤트의 경우
      • 새로운 트럭이 다리에 진입할 때
      • 다리위의 트럭이 다리의 끝에 도달할 때
    • 지속적 이벤트의 경우
      • 한 턴마다 시간이 1씩 증가함
      • 트럭이 1초마다 다리를 1씩 지나감

    나의 코드

    const solution = (bridgeLength, weight, truckWeigths) => {
      let time = 0;
      let passingWeight = 0;
      let passingTrucksWeigth = [];
      let passingTrucks = [];
      let passedTrucks = [];
      let index = 0;
    
      while (passedTrucks.length < truckWeigths.length) {
        // 지속적인 이벤트 -1 while문 한번 돌 때 시간 +1
        time++;
    
        // 특별한 이벤트 1 - passingWeight가 weight보다 작은 경우 passingTrucks와 passingWeight를 더한다
        if (passingWeight + truckWeigths[index] <= weight) {
          passingTrucks.push(0);
          passingTrucksWeigth.push(truckWeigths[index]);
          passingWeight += truckWeigths[index];
          index++;
        }
    
        // 지속적인 이벤트 - 2 passingTrucks의 값이 0부터 시작하여 length 도달까지 +1
        for (let i = 0; i < passingTrucks.length; i++) {
          passingTrucks[i] += 1;
    
          // 특별한 이벤트 2 - passingTrucks 중 하나가 bridgeLength에 도달하면 passingWeight과 passingTrucks에 빼고 passedTrucks에 추가
          if (passingTrucks[i] === bridgeLength) {
            passedTrucks.push(passingTrucksWeigth[i]);
            passingWeight -= passingTrucksWeigth[i];
            passingTrucksWeigth.shift();
            passingTrucks.shift();
            i--;
          }
        }
      }
    
      return time + 1;
    };

     

    코드특징

    • 지속적 이벤트와 특별한 이벤트를 나눠서 코드를 작성했다
    • while문을 한 번 돌때 시간은 1씩 증가 (지속적 이벤트 1)
    • 무게한계보다 낮아 트럭 한개가 진입이 가능한 경우 (특별한 이벤트 1)
      • passingTrucks[]에 0을 넣어 이를 알림.
      • passingTrucksWeight[]에 어느 트럭이 지나가고 있는지 값을 넣는다.
      • passingWeight에 현재 다리 위에 트럭들 무게의 합을 구한다. 
    • passingTrucks[] 을 for문을 통해 현재 다리를 지나는 트럭들이 1씩 움직이도록 증가함 (지속적 이벤트 2)
    • passingTrucks[] 내의 어느 트럭이 다리 끝에 도달하여 빠져나간 경우 (특별한 이벤트 2)
      • passedTrucks[]에 어느 트럭이 빠져나왔는지 알림
      • passingWeight에 빠져나간 트럭 무게를 뺌
      • passingTrucksWeight[]에 빠져나간 트럭을 지움 (array.prototype.shift를 활용)
      • passingTrucks[]에 빠져나간 트럭을 지움 (array.prototype.shift를 활용)
      • 트럭을 지워 돌고 있는 for문에 영향을 주기 때문에 i--

     

    코드성능

    • 2중 for문에 참조하는 배열들이 너무 많아 무거워진 탓에 성능이 안 좋은 것을 알 수가 있다 
    • 불필요한 배열들을 삭제하여 좀 더 효율적인 코드로 수정할 필요가 있다

    다른 사람 풀이법 1

    function solution(bridge_length, weight, truck_weights) {
      // '다리'를 모방한 큐에 간단한 배열로 정리 : [트럭무게, 얘가 나갈 시간].
      let time = 0, qu = [[0, 0]], weightOnBridge = 0;
    
      // 대기 트럭, 다리를 건너는 트럭이 모두 0일 때 까지 다음 루프 반복
      while (qu.length > 0 || truck_weights.length > 0) {
        // 1. 현재 시간이, 큐 맨 앞의 차의 '나갈 시간'과 같다면 내보내주고,
        //    다리 위 트럭 무게 합에서 빼준다.
        if (qu[0][1] === time) weightOnBridge -= qu.shift()[0];
    
        if (weightOnBridge + truck_weights[0] <= weight) {
          // 2. 다리 위 트럭 무게 합 + 대기중인 트럭의 첫 무게가 감당 무게 이하면 
          //    다리 위 트럭 무게 업데이트, 큐 뒤에 [트럭무게, 이 트럭이 나갈 시간] 추가.
          weightOnBridge += truck_weights[0];
          qu.push([truck_weights.shift(), time + bridge_length]);
        } else {
          // 3. 다음 트럭이 못올라오는 상황이면 얼른 큐의
          //    첫번째 트럭이 빠지도록 그 시간으로 점프한다.
          //    참고: if 밖에서 1 더하기 때문에 -1 해줌
          if (qu[0]) time = qu[0][1] - 1;
        }
        // 시간 업데이트 해준다.
        time++;
      }
      return time;
    }

    코드특징

    • qu[][]를 통해 트럭무게와 해당 트럭이 다리 끝에 도달할 시간을 저장하여 이 둘을 핵심적으로 활용
      • 나의 코드는 프로세스 위주로 보지만 이 분은 거시적인 관점에서 보기에 더 효율적이며 깔끔하게 접근함 
    • 다음 트럭이 못 올라올 경우 시간 워프를 통해 불필요하게 while문을 돌리지 않게 함

     

    코드성능

    • 역시 빠르다!

    오늘 배운점

    • 프로세스를 한번 정리하는 것은 좋다... 덕분에 풀긴풀었자너... 그러나 이에 만족하지 않고 한 번 더 생각해서 성능을 더 높일 수 있는 방안을 생각하자

    '알고리즘' 카테고리의 다른 글

    방문길이  (0) 2021.09.23
    땅따먹기  (0) 2021.09.14
    스킬트리  (0) 2021.09.11
    영어 끝말잇기  (0) 2021.09.09
    구명보트  (0) 2021.09.08
Designed by Tistory.