솔직히 이 문제를 어떻게 이분 탐색으로 풀어야 할지 감이 안왔고 자바 근본 알고리즘 블로그 stranger's lab님의 풀이법을 보고 풀었다. 볼 때 마다 풀이법과 설명 방식에 감탄한다.
lower bound (하한)
upper bound (상한)
https://bajamircea.github.io/coding/cpp/2018/08/09/lower-bound.html
int start = 0;
int end = arr.length;
int value = ? // 찾고자 하는 값
while (start < end) {
int mid = (start + end) / 2;
//end를 mid로 좁힌다.
if (arr[mid] >= value) {
end = mid;
}
//start를 mid+1로 좁힌다.
else {
start = mid + 1;
}
}
[10, 20, 30, 15, 20, 30, 50, 40, 45 ,60]
배열의 LIS를 구한다 가정
현재 값 | dp | 결과 |
---|---|---|
10 | [10] | |
20 | [10] | [10, 20] |
30 | [10, 20] | [10, 20, 30] |
15 | [10, 20, 30] | [10, 15, 30] |
20 | [10, 15, 30] | [10, 15, 20] |
30 | [10, 15, 20] | [10, 15, 20, 30] |
50 | [10, 15, 20, 30] | [10, 15, 20, 30, 50] |
40 | [10, 15, 20, 30, 50] | [10, 15, 20, 30, 40] |
45 | [10, 15, 20, 30, 40] | [10, 15, 20, 30, 40, 45] |
60 | [10, 15, 20, 30, 40, 45] | [10, 15, 20, 30, 40, 45, 60] |
public class p12015 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int N = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
int[] arr = new int[N];
int[] dp = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
dp[0] = arr[0];
int LIS_length = 1;
for (int i = 1; i < N; i++) {
if(dp[LIS_length-1]<arr[i]) {
dp[LIS_length] = arr[i];
LIS_length++;
}
else {
int start = 0;
int end = LIS_length;
while (start < end) {
int mid = (start + end) / 2;
if (dp[mid] >= arr[i]) {
end = mid;
}
else {
start = mid + 1;
}
}
dp[start] = arr[i];
}
}
System.out.println(LIS_length);
}
}