코딩테스트 연습 - 택배 배달과 수거하기 | 프로그래머스 스쿨 (programmers.co.kr)

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

풀다가 다른 사람 풀이를 보니 현타가 와서.. 작성하는 글.

다른 사람 풀이

class Solution {
    public long solution(int cap, int n, int[] deliveries, int[] pickups) {
        long answer = -1;
        int deliver = 0, pickup = 0;
        for(int i = n-1; i >= 0; i--){
            deliver += deliveries[i];
            pickup += pickups[i];
            while (deliver > 0 || pickup > 0){
                deliver -= cap;
                pickup -= cap;
                answer += ((i+1) * 2);
            }

        }
        return answer + 1;
    }
}
  1. 배열 끝부터 돌면서 
  2. 총 배송 박스 수와 수거해야 하는 박스 수를 구하고
  3. 둘 중 하나가 0 일 때까지 각각 cap을 빼주고
  4. i는 가장 먼 거리를 의미하니까, delivery가 멀든, pickup이 더 멀든 결과적으로 (i + 1) * 2를 하면 한 번 왕복 거리가 된다.
  5. 근데 while (delivery > 0 || pickup > 0)이 참 이면 = 아직 배달 or 수거할게 남은 거니까 = 한 번 더 가야 하므로 while loop을 한 번 더 돈다.
  6. for 문을 돌며 처음 지점까지 가면 끝

인터넷 풀이를 보면 stack을 사용하거나, 재귀 등등 풀이법이 많다.

아래 코드는 내가 작성한 코드..

class Solution {
    public long solution(int cap, int n, int[] deliveries, int[] pickups) {
        
        long totalDistance = 0;
        int deliveryIndex = n - 1;
        int pickupIndex = n - 1;

        while (deliveryIndex >= 0 || pickupIndex >= 0) {
            int currentDeliveryCapacity = 0;
            int currentPickupCapacity = 0;
            int furthestIndex = 0;

            // 가장 멀리 갈 집 찾기
            while (deliveryIndex >= 0 && deliveries[deliveryIndex] == 0) {
                deliveryIndex--;
            }
            while (pickupIndex >= 0 && pickups[pickupIndex] == 0) {
                pickupIndex--;
            }

            // 배달과 수거를 해야 할 가장 멀리 있는 집을 찾음
            furthestIndex = Math.max(deliveryIndex, pickupIndex);

            // 왕복 거리 추가
            totalDistance += (furthestIndex + 1) * 2;

            // 배달 처리
            while (deliveryIndex >= 0 && currentDeliveryCapacity < cap) {
                if (deliveries[deliveryIndex] > 0) {
                    int deliverable = Math.min(cap - currentDeliveryCapacity, deliveries[deliveryIndex]);
                    deliveries[deliveryIndex] -= deliverable;
                    currentDeliveryCapacity += deliverable;
                }
                if (deliveries[deliveryIndex] == 0) {
                    deliveryIndex--;
                }
            }

            // 수거 처리
            while (pickupIndex >= 0 && currentPickupCapacity < cap) {
                if (pickups[pickupIndex] > 0) {
                    int pickupable = Math.min(cap - currentPickupCapacity, pickups[pickupIndex]);
                    pickups[pickupIndex] -= pickupable;
                    currentPickupCapacity += pickupable;
                }
                if (pickups[pickupIndex] == 0) {
                    pickupIndex--;
                }
            }
        }

        return totalDistance;
    }
}

사실 이것도 GPT 도움 받아서 완성한거... 

근데 다른 사람 풀이를 보니 저렇게 직관적이고 간단하게 풀 수 있구나 싶어서

현타가 왔다..

 

다른 사람 풀이와 차이점?

for 끝 부터 순회하면서 어차피 배달/수거할 게 없으면 0 이니까 둘 중 하나 0보다 커지면 그때 거리를 계산하면 된다.

나는 매번 배달/수거 해야할 가장 먼 거리 인덱스를 찾는 로직이 들어있다.

 

그래서 나는 인덱스를 구하다 보니, 매 조건문에 인덱스 범위를 체크하는 조건이 들어있고 나는 초점을 이번 루프에서 담을 공간이 얼마나 남았냐 로 두었는데, 다른 사람 풀이는 이번 루프에서 총 몇 개를 배달/수거해야 하는가? 이다.

그래서 나는 남은 공간을 계산하는 로직이 들어있고, 이를 배달, 수거로 분리하니 로직이 같은 코드가 2배가 된 것 같다.

마치며

  • 나도 저렇게 핵심만 뽑아서 코드로 구현할 수 있었으면 좋겠다.