원소가 n개인 배열의 일부 원소를 골라만든 부분 수열 중 각 원소가 이전 원소보다 크다는 조건을 만족하고, 그 길이가 최대인 부분 수열
일반적으로 LIS 의 길이가 얼마인지 푸는 간편한 방법은 DP를 이용하는 것
int max = 0;
for (int i = 0; i < N; i++) {
LIS[i] = 1; // 자신만 끝에 세울 경우 1의 길이
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
LIS[i] = Math.max(LIS[i], LIS[j] + 1);
}
}
max = Math.max(max, LIS[i]);
}
j 번째 인덱스에서 끝나는 LIS의 마지막에 arr[i] 를 추가했을 때의 LIS 의 길이
추가하지 않은 기존의 LIS[i] 의 값
1 과 2 중 더 큰 값으로 LIS[i] 의 값을 업데이트
시간복잡도 개선을 위해 LIS 구성 시 이진탐색을 활용
LIS 의 형태를 유지하기 위해 주어진 배열의 인덱스를 하나씩 살펴보면서 그 숫자가 들어갈 위치를 이진탐색으로 탐색해서 넣음
int size = 0;
for (int i = 0; i < N; i++) {
// 이진 탐색을 통해 삽입 위치 탐색
int idx = Arrays.binarySearch(LIS, 0, size, nums[i]);
idx = Math.abs(idx) - 1;
// idx 자리에 값 갱신 : 0 번부터 idx 번까지 원소 개수가 idx 위치에 저장된
// 그 값을 마지막으로 하는 LIS 길이가 됨
// 배열의 원소가 LIS를 이루는 구성 요소와는 관계가 없음
LIS[idx] = nums[i];
if (size == idx) {
size++;
}
}