https://www.acmicpc.net/problem/11053
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
잘못된 풀이
모든 경우의 수를 파악한다.
N이 5인 경우 2^N의 경우를 확인해야한다.
N이 1000 이하이므로 부적합하다.
패턴 이용
위의 수열 A = {10, 20, 10, 30, 20, 50} 에서첫 번째 10 뒤에 올 수 있는 수는 {20, 30, 20, 50} 이다.
그리고 길이는 2이다.첫 번째 20 뒤에 올 수 있는 수는 {30, 50} 이다.
그리고 길이는 3이다.왜 3일까?
첫 번째 20은 10부터 시작하는 수열이다.
따라서 10-20-30 또는 10-20-50으로 이어질 수 있다.즉, 특정 숫자는 수열의 왼편에 있는 숫자들 보다 큰 경우 이어질 수 있다.
가장 긴 수열을 구해야 하므로, 왼편에 있는 숫자 중 수열이 긴 경우만 판단해 이으면 된다.패턴은 아래와 같다.
1. 반복문을 통해 두 수(i,j)를 비교한다.(i:1~N-1, j:i+1~N)
2. j가 i보다 크고, i수열 길이보다 짧다면
3. j의 수열 길이는 i+1이 된다. 즉, j는 i를 잇는 수열이다.아래는 비교를 통해 얻을 수 있는 수열의 길이를 나타냈다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// input | N->int, stk->StringTokenizer
int N = Integer.parseInt(br.readLine());
StringTokenizer stk = new StringTokenizer(br.readLine());
// init | Ai->int[] Using stk , asc & desc->Stack<Integer>
int[][] Ai = new int[N][2];
for(int i=0; i<N; i++){
Ai[i][0] = Integer.parseInt(stk.nextToken());
Ai[i][1] = 1;
}
// solve |
int answer = 1;
for(int i=0; i<N-1; i++){
for(int j=i+1; j<N; j++){
if(Ai[i][0]<Ai[j][0] && Ai[i][1]>=Ai[j][1]){
Ai[j][1] = Ai[i][1]+1;
if(Ai[j][1]>answer)
answer = Ai[j][1];
}
}
}
// print
System.out.println(answer);
}
}
