[BOJ] 14002. 가장 긴 증가하는 부분수열4
LIS 알고리즘 - 이진탐색(NlogN)
- 메모리 : 13,340 KB
- 시간 : 88 ms
- 코드길이 1,562 B
- 소요시간 : 45M
- 이진 탐색에서 같은 숫자를 찾을 경우 그 자리의 index를 주기때문에 temp값에 음수가 나와서 처음에 런타임 에러가 떳었다. 그래서 음수값이 나오는 경우는 이미 배열에 있기 때문에 패스하는 if (temp < 0) continue;를 추가해주었더니 통과할 수 있었다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main_B_14002_가장긴증가하는부분수열4_이진탐색 {
static int N, num[];
static StringBuilder answer = new StringBuilder();
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
num = new int[N];
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int i = 0; i < N; i++) {
num[i] = Integer.parseInt(st.nextToken());
}
lisPath();
System.out.println(answer);
in.close();
}
private static void lisPath() {
int[] lis = new int[N];
int[] lisIndex = new int[N];
int[] preIndex = new int[N];
int size = 0, temp = 0;
for (int i = 0; i < N; ++i) {
temp = -(Arrays.binarySearch(lis, 0, size, num[i])) - 1;
if (temp < 0) continue; // 같은 숫자를 찾을 경우는 패스
lis[temp] = num[i];
lisIndex[temp] = i;
// 자신의 위치가 0(첫번째)이면 이전은 없고, 자신의 위치가 0이 아니라면 현재 lis 구성의 바로 직전이 이전됨.
preIndex[i] = (temp == 0) ? -1 : lisIndex[temp - 1];
if (temp == size)
++size;
}
answer.append(size).append('\n');
// 경로 출력을 위한 코드
int cur = lisIndex[size - 1];
Stack<Integer> stack = new Stack<Integer>();
while (cur != -1) {
stack.push(num[cur]);
cur = preIndex[cur];
}
while (!stack.isEmpty()) {
answer.append(stack.pop()).append(' ');
}
}
}
LIS 알고리즘 - DP
- 메모리 : 13,656 KB
- 시간 : 100 ms
- 코드길이 : 1,400 B
- 소요시간 : 15M
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main_B_14002_가장긴증가하는부분수열4_DP {
static int N, num[];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
num = new int[N];
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int i = 0; i < N; i++) {
num[i] = Integer.parseInt(st.nextToken());
} // end input
lisPath();
} // end main
private static void lisPath() {
StringBuilder answer = new StringBuilder();
int lis[] = new int[N]; // 길이를 담을 배열
int pre[] = new int[N]; // 경로를 추척할 인덱스를 담을 배열
int maxIndex = 0;
for (int i = 0; i < N; ++i) {
lis[i] = 1;
pre[i] = -1;
for (int j = 0; j < i; ++j) {
if (num[i] > num[j] && lis[i] < lis[j] + 1) {
lis[i] = lis[j] + 1;
pre[i] = j;
if (lis[maxIndex] < lis[i])
maxIndex = i;
}
}
}
answer.append(lis[maxIndex]).append('\n');
int cur = maxIndex;
Stack<Integer> stack = new Stack<Integer>();
while (cur != -1) {
stack.push(num[cur]);
cur = pre[cur];
}
while (!stack.isEmpty()) {
answer.append(stack.pop()).append(' ');
}
System.out.println(answer);
} // end listPath
}
Leave a comment