수열 S가 어떤 수 S(k)를 기준으로 S(1) < S(2) < ... S(k-1) < S(k) > S(k+1) > ... S(N-1) > S(N)을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.
예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만, {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.
수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.
10
1 5 2 1 4 3 4 5 2 1
7
💡 바이토닉 수열이란?
어떤 수를 기준으로 증가하다 작아지는 수열
dp에는 길이를 담자.A[0]부터 A[A.length - 1]까지 순서대로 해보기로~leftDp) & 오른쪽으로 갈수록(rightDp) 더 작아지는지 확인index를 기준으로, 왼쪽부터 오름차순 길이 & 오른쪽부터 오름차순 길이가 합해진다!!1개 중복이니까 1씩 빼주기-1 해줘도 될 것.import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
private static int[] arr;
private static Integer[] leftDp;
private static Integer[] rightDp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
leftDp = new Integer[N];
rightDp = new Integer[N];
for (int i = 0; i < N; i++) {
lis(i);
lds(i);
}
int max = -1;
for (int i = 0; i < N; i++) {
max = Math.max(leftDp[i] + rightDp[i], max);
}
System.out.println(max - 1);
}
private static int lis(int N) {
if (leftDp[N] == null) {
leftDp[N] = 1;
for (int i = N - 1; i >= 0; i--) {
if (arr[i] < arr[N]) {
leftDp[N] = Math.max(leftDp[N], lis(i) + 1);
}
}
}
return leftDp[N];
}
private static int lds(int N) {
if (rightDp[N] == null) {
rightDp[N] = 1;
for (int i = N + 1; i < rightDp.length; i++) {
if (arr[i] < arr[N]) {
rightDp[N] = Math.max(rightDp[N], lds(i) + 1);
}
}
}
return rightDp[N];
}
}
private static int lis(int N) {
if (leftDp[N] == null) {
leftDp[N] = 1;
for (int i = N - 1; i >= 0; i--) {
if (arr[i] < arr[N]) {
leftDp[N] = Math.max(leftDp[N], lis(i) + 1);
}
}
}
return leftDp[N];
}
내가 고민했던 부분은 재귀함수를 호출하고 결과에 1을 더하는 부분이다.
이전에 계산한 길이를 추가해주는데 항상 1을 더한다는 걸 어떻게 보장하지?
라고 생각했다.
재귀함수를 부른다는 것 자체가 탐색하지 않은 위치이기에 가능한 것이므로 길이는 현재 기준으로 잡은 S(k) 하나, 즉 길이가 1일 수 밖에 ㅎㅎ ..