개요
이 문제는 2가지 정도의 풀이가 존재한다.
1. 동적 프로그래밍
2. 이분 탐색
하지만, 이 문제의 입력에서 n의 값이 1,000,000 이기 때문에 이분 탐색으로 풀이하여야 시간 초과를 피할 수 있다.
간단히 설명하자면 우리가 구하고자 하는 증가 수열을 List 자료구조에 저장하고
새로 들어온 값에 대해서 list 안에서의 위치를 찾아 list를 갱신해주는 것이다.
문제
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.
입력
풀이
개요에서 말했듯이 이분탐색을 이용해서 수열의 적당한 위치를 찾아 줄 것이다.
입력된 값의 처음부터 순차적으로 검사를 시작한다. 검사를 할 때 아래와 같이 2가지 경우로 나뉘게 된다.
- 검사하는 숫자가 증가수열 리스트의 마지막 숫자보다 큰 경우
→ 증가수열 리스트에 추가한다.
- 검사하는 숫자가 증가수열 리스트의 마지막 숫자보다 작은 경우
→ 증가수열 리스트내의 적당한 위치를 찾아서 갱신한다.
예제 입력과 같이 입력이 들어왔을 때의 시퀀스는 아래와 같다. (증가수열 리스트이다.)
위와 같이 시퀀스가 나타나고 최종적으로 list길이를 이용하여 정답을 도출해 낼 수 있다.
단, list에 저장된 숫자들이 실제 증가 수열이 되는 것은 아니다.
그 이유는 10 20 30 14 24 50 과 같은 입력을 해보며 손으로 그려보면 알 수 있다.
만약 실제 증가수열의 값들을 구하고 싶다면 아마도 역추적을 통해 구할 수 있을 것이다.
코드
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
// 증가수열을 저장할 리스트
List<Integer> list = new ArrayList<>();
// 입력된 값을 저장할 배열
int arr[] = new int[n + 1];
for(int i = 1 ; i <= n; i++) arr[i] = Integer.parseInt(st.nextToken());
list.add(Integer.MIN_VALUE);
for(int i = 1 ; i <= n; i++){
int num = arr[i];
int left = 1;
int right = list.size() - 1;
// 확인하는 숫자가 증가수열의 마지막 수보다 큰 경우
// 수열에 추가해준다.
if(num > list.get(list.size() - 1)) list.add(num);
// 확인하는 숫자가 증가수열의 마지막 수보다 작은 경우
else{
// 숫자의 적당한 위치를 찾아
// 증가수열의 값을 변경해준다.
while(left < right){
int mid = (left + right) >> 1;
if(list.get(mid) >= num) right = mid;
else left = mid + 1;
}
list.set(right, num);
}
}
// 최장 길이 출력
sb.append(list.size() - 1 + "\n");
bw.write(sb.toString());
bw.close();
br.close();
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준 9019: JAVA] DSLR / BFS, 역추적 (0) | 2020.03.14 |
---|---|
[백준 13913: JAVA] 숨바꼭질 4 / DP, BFS, 역추적 (0) | 2020.03.14 |
[백준 14002: JAVA] 가장 긴 증가하는 부분 수열 4/ 동적 프로그래밍 + 역추적 (0) | 2020.02.19 |
[백준 12852: JAVA] 1로 만들기 2 / 동적 프로그래밍 + 역추적 (0) | 2020.02.19 |
[백준 2482: JAVA] 색상환 / 동적 프로그래밍 (0) | 2020.02.19 |