https://school.programmers.co.kr/learn/courses/30/lessons/64062
Level 3
카카오 초등학교의 "니니즈 친구들"이 "라이언" 선생님과 함께 가을 소풍을 가는 중에 징검다리가 있는 개울을 만나서 건너편으로 건너려고 합니다. "라이언" 선생님은 "니니즈 친구들"이 무사히 징검다리를 건널 수 있도록 다음과 같이 규칙을 만들었습니다.
"니니즈 친구들"은 개울의 왼쪽에 있으며, 개울의 오른쪽 건너편에 도착해야 징검다리를 건넌 것으로 인정합니다.
"니니즈 친구들"은 한 번에 한 명씩 징검다리를 건너야 하며, 한 친구가 징검다리를 모두 건넌 후에 그 다음 친구가 건너기 시작합니다.
디딤돌에 적힌 숫자가 순서대로 담긴 배열 stones와 한 번에 건너뛸 수 있는 디딤돌의 최대 칸수 k가 매개변수로 주어질 때, 최대 몇 명까지 징검다리를 건널 수 있는지 return 하도록 solution 함수를 완성해주세요.
[제한사항]
class Solution {
public int solution(int[] stones, int k) {
int left = 1;
int right = 0;
for (int s : stones) right = Math.max(right, s);
while(left <= right){
int mid = (left + right) / 2;
if(canCross(stones, k, mid)){
left = mid + 1;
}else{
right = mid - 1;
}
}
return right;
}
public boolean canCross(int[] stones, int k, int mid){
int skip = 0;
for(int stone : stones){
if(stone < mid){
skip++;
if(skip >= k) return false;
}else{
skip = 0;
}
}
return true;
}
}


완전탐색이 불가능한 문제이다.
따라서 연속된 k개의 돌이 모두 0 이하가 되는 순간을 찾아 최대로 건널 수 있는 인원의 수를 찾아야 한다.
-> 즉, 연속으로 k개 이상의 돌이 부서지면 건너지 못함을 인지 해야한다.
그럼 최대로 건널 수 있는 인원의 수에 집중하며 이분 탐색을 적용해야한다.
탐색 범위는 1명(left)부터 돌 배열(stones)의 값 중 가장 큰 값(right)까지 설정한다.
이때, mid명의 사람이 건널 수 있는지를 판단하는 canCross 함수를 구현한다.
이 함수는 연속으로 k개 이상의 돌이 부서지는 경우 존재하는지를 검사하는 역할을 한다.
canCross(mid)가 true이면 mid명까지는 건널 수 있다는 의미이므로, 더 많은 인원도 시도해본다.
반대로 false이면 인원이 너무 많아 돌이 연속으로 부서지므로, 인원을 줄여야 한다.
이 과정을 통해 건널 수 있는 최대 인원 수를 이분 탐색으로 효율적으로 구할 수 있다.