[프로그래머스 / Python] 징검다리

Kun-Woo Kim·2025년 2월 5일

알고리즘 공부

목록 보기
20/24
post-thumbnail

문제 출처

문제 보러가기


문제

출발지점부터 distance만큼 떨어진 곳에 도착지점이 있습니다. 그리고 그 사이에는 바위들이 놓여있습니다. 바위 중 몇 개를 제거하려고 합니다.

예를 들어, 도착지점이 25만큼 떨어져 있고, 바위가 [2, 14, 11, 21, 17] 지점에 놓여있을 때 바위 2개를 제거하면 출발지점, 도착지점, 바위 간의 거리가 아래와 같습니다.

제거한 바위의 위치각 바위 사이의 거리거리의 최소값
[21, 17][2, 9, 3, 11]2
[2, 21][11, 3, 3, 8]3
[2, 11][14, 2, 4, 4]2
[11, 21][2, 12, 3, 8]2
[2, 14][11, 6, 4, 4]4

위에서 구한 거리의 최소값 중에 가장 큰 값은 4입니다.

출발지점부터 도착지점까지의 거리 distance, 바위들이 있는 위치를 담은 배열 rocks, 제거할 바위의 수 n이 매개변수로 주어질 때, 바위를 n개 제거한 뒤 각 지점 사이의 거리의 최소값 중에 가장 큰 값을 return 하도록 solution 함수를 작성해주세요.


제한사항

  • 도착지점까지의 거리 distance1 이상 1,000,000,000 이하입니다.
  • 바위는 1개 이상 50,000개 이하가 있습니다.
  • n1 이상 (바위의 개수) 이하입니다.

첫번째 제출 답안

def solution(distance, rocks, n):
    rocks.sort()
    left, right = 0, distance
    answer = 0
    
    while left <= right:
        mid = (left + right) // 2
        prev, removed = 0, 0
        
        for rock in rocks:
            if rock - prev < mid:
                removed += 1
                if removed > n:
                    break
            else:
                prev = rock
        
        if removed > n:
            right = mid - 1
        else:
            left = mid + 1
            answer = mid
        
    return answer

위 코드를 실행했을 때 일부 테스트에서 실패가 발생했다.


수정된 답안

def solution(distance, rocks, n):
    rocks.append(distance)  # 도착 지점을 rocks에 추가
    rocks.sort()  # 바위를 정렬하여 거리 계산을 용이하게 함
    left, right = 0, distance
    answer = 0
    
    while left <= right:
        mid = (left + right) // 2  # 이분 탐색으로 최소 거리 찾기
        prev, removed = 0, 0
        
        for rock in rocks:
            if rock - prev < mid:  # mid보다 작은 거리의 바위 제거
                removed += 1
                if removed > n:  # 제거할 수 있는 개수를 초과하면 종료
                    break
            else:
                prev = rock  # 바위를 유지하고 다음 거리 계산
        
        if removed > n:  # 너무 많은 바위를 제거했다면 mid를 줄임
            right = mid - 1
        else:  # 현재 설정에서 최소 거리(mid)를 유지할 수 있다면 mid를 늘려봄
            left = mid + 1
            answer = mid  # 최소 거리 값을 갱신
        
    return answer

초기 코드에서 도착 지점(distance)을 rocks 리스트에 추가하는 부분이 빠져 있었기 때문에 테스트에서 실패했다. 이를 보완한 후 테스트를 다시 실행해 보니 모든 테스트 케이스를 통과했다.


결론 및 느낀점

이번 문제를 풀면서 이분 탐색과 그리디 알고리즘을 함께 활용하는 방법을 배울 수 있었습니다. 처음에는 단순히 거리의 최댓값을 찾으려고 했지만, 바위 제거 과정에서 도착 지점을 고려하지 않아 일부 테스트에서 실패했습니다. 이를 해결하기 위해 도착 지점도 rocks에 추가하고, 각 구간의 거리를 신중하게 계산하는 방식으로 수정하니 모든 테스트를 통과할 수 있었습니다.

이 문제의 핵심 알고리즘은 이분 탐색(Binary Search)입니다. 하지만 단순한 이분 탐색이 아니라, 바위를 제거하는 과정에서 그리디 알고리즘(Greedy Algorithm)이 적용되었습니다.

특히, for rock in rocks: 문에서 rock - prev < mid인 경우 가장 가까운 바위를 우선 제거하는 방식이 적용되어 있습니다. 즉, 최대한 적은 바위를 제거하면서 mid 이상의 거리를 유지하려고 하는 전략이 그리디한 선택이 됩니다.

이번 문제를 통해 이분 탐색과 그리디 알고리즘이 결합될 수 있는 문제 유형을 이해할 수 있었고, 탐색 과정에서 예외 처리가 중요하다는 점도 다시 한번 느꼈습니다.

profile
안녕하세요, 김건우입니다! 웹과 앱 개발에 열정적인 전문가로, Next.js 14, Node.js, Express, Flutter 등을 활용한 프로젝트를 다룹니다. 제 블로그에서는 개발 여정, 기술 분석, 실용적 코딩 팁을 공유합니다. 창의적인 솔루션을 실제로 적용하는 과정의 통찰도 나눌 예정이니, 궁금한 점이나 상담은 언제든 환영합니다.

0개의 댓글