본문 바로가기
프로그래밍/Python

[프로그래머스] 징검다리 / 이진 탐색 / python

by 나는 라미 2024. 3. 7.
728x90
반응형
 
 

프로그래머스

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

programmers.co.kr

문제

출발지점부터 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, 3, 4, 4]
3
[11, 21]
[2, 12, 3, 8]
2
[2, 14]
[11, 6, 4, 4]
4

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

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

제한사항

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

풀이

아이디어

무작정 계산한다고 치면 50,000Cn으로 나오는 바위의 경우의 수를 계산하면 된다

엄청난 계산량이 예상되는 걸 보니 이렇게 구하는 것이 아닐지도 모른다는 생각이 든다

사실 카테고리가 이분탐색이기 때문에.. ㅎㅎ

모든 경우의 수를 계산하지 않고 제거할 바위를 구하도록 하자!

 

💥 tip

데이터가 엄청 큰 경우, 이분탐색을 사용해야할 가능성이 높음

  • 이분탐색은 start, end을 설정이 중요
  • mid는 return하는 정보에 관한 데이터라는 점

 

return해야할 정보

각 바위사이의 거리의 최솟값중 최대값

 

이분탐색으로 return하는 정보와 mid는 관련이 있다는 점을 상기시켜, mid 값은 각 바위사이의 거리의 최솟값이 된다.

 

확인해야할 조건은 삭제한 바위의 개수가 n보다 작은지 봐야한다

삭제한 바위의 개수가 n보다 큰 경우 조건을 만족하지 않기때문에 mid값을 조정해야한다

- end = mid -1

- end 값을 줄여 mid 값을 줄여준다

 

삭제한 바위의 개수가 n보다 작거나 같은 경우에는 mid를 다음과 같이 조정한다

- start = mid + 1

- start 값을 늘려 mid 값을 올린다. mid 값을 늘려 제거할 바위의 개수를 늘림

 

코드

def solution(distance, rocks, n):
    rocks.sort()        #이분탐색을 위한 정렬
    rocks.append(distance)
    start, end = 0, rocks[-1]   
    while start <= end:
        mid = (start + end ) // 2
        cnt_remove = 0  #제거한 바위의 개수
        current = 0 #현재 위치_처음 시작위치: 0
        
        # 제거할 바위의 개수 세기
        for rock in rocks:
            dist = rock - current   #현재위치와 바위사이의 거리
            
            if dist < mid:  #dist가 mid보다 작으면 바위삭제
                cnt_remove += 1
                if cnt_remove > n :#삭제한 바위의 개수가 n보다 큰 경우 더이상 계산x
                    break
            else:   #거리가 mid보다 같거나 큰 경우
                current = rock
                
        if cnt_remove > n:
            end = mid - 1
        else:
            answer = mid
            start = mid + 1
                
    return answer​
 
728x90
반응형

댓글