코딩테스트
[softeer/java] 징검다리
dev-mong2
2025. 2. 3. 17:03

문제
남북으로 흐르는 개울에 동서로 징검다리가 놓여져 있다.
이 징검다리의 돌은 들쑥날쑥하여 높이가 모두 다르다. 철수는 개울의 서쪽에서 동쪽으로 높이가 점점 높은 돌을 밟으면서 개울을 지나가려고 한다.
돌의 높이가 서쪽의 돌부터 동쪽방향으로 주어졌을 때 철수가 밟을 수 있는 돌의 최대 개수는?
제약조건
1 ≤ N ≤ 3×103 인 정수
1 ≤ Ai ≤ 108 인 정수
입력형식
첫 번째 줄에 돌의 개수 N이 주어진다.
두 번째 줄에 돌의 높이 Ai (1 ≤ i ≤ N)가 서쪽부터 동쪽으로 차례로 주어진다.
출력형식
첫 번째 줄에 철수가 밟을 수 있는 돌의 최대 개수를 출력하라.
입력예제
5
3 2 1 4 5
처음에는 단순히 앞 뒤로 비교 후 뒤 값이 크면 count++ 형식으로 하려했으나...
철수가 돌을 뛰어 넘을 수도 있기 때문에 해당 방법은 틀린 방법이다.
저 방법은 철수가 걷기만 가능할 때 유효함.
따라서 이분탐색으로 해결하기로 함
현재 원소와 뒤의 원소를 이분 탐색하여 최종 배열 길이를 출력해주면 된다.
현재 원소보다 큰 값일 찾기위해 이분 탐색을 사용하는거임
과정
- 3 → list = [3]
- 4 → list = [3, 4]
- 1 → list = [1, 4] (3이 1로 대체됨)
- 2 → list = [1, 2] (4가 2로 대체됨)
- 5 → list = [1, 2, 5] (5 추가됨)
정답
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //돌의 개수
int[] arr = new int[n]; //돌의 높이 배열, 낮은곳에서 높은곳으로 뛰어 넘을 수도 있음. 그래서 단순 count++ 방법은 불가
for (int i=0 ; i<n ; i++) {
arr[i] = sc.nextInt();
}
//이분 탐색 배열
int[] list = new int[n];
int len = 0;
for (int i=0 ; i<n ; i++) {
//현재 돌의 높이를 list 배열 내에 삽입할 위치를 이분 탐색으로 찾는다.
int pos = Arrays.binarySearch(list, 0, len, arr[i]);
if (pos < 0) { //음수라면?
pos = -(pos + 1);
}
list[pos] = arr[i]; //해당 위치에 현재 값을 삽입
//만약 list의 끝에 새 값을 추가한 경우라면 길이를 늘린다.
if (pos == len) {
len++;
}
}
System.out.println(len); //배열 길이를 출력
}
}
