[백준] 2352번 반도체 설계 - Java/자바
문제
입력
첫째 줄에 정수 n(1 ≤ n ≤ 40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, …, n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자.
출력
첫째 줄에 최대 연결 개수를 출력한다.
접근방법
가장 긴 증가하는 부분수열(Longest Increasing Subsequence)을 구하는 문제다.
11053번 가장 긴 증가하는 부분수열
에서도 다룬 적이 있다.
하지만 저번 문제에서는 동적계획법을 활용해서 풀었다면, 이번 문제에서는 이진탐색을 이용해 해결했다.
참고로, 동적계획법 풀이는 O(n^2)의 시간복잡도를, 이분탐색을 활용한 풀이는 O(nlog n)의 시간복잡도를 가진다.
우선, arr
배열을 탐색하면서 각 요소가 LIS를 만들 수 있는지를 검사한다. 여기서 dp
배열에 채워진 길이는 arr
배열에서의 해당 위치에서 가질 수 있는 LIS의 길이를 의미한다.
만약 배열의 값이 현재까지 구한 dp
배열의 모든 요소보다 크다면 dp
배열의 마지막에 위치하게 되고, dp
배열에 채워진 요소 중 하나보다 작다면 dp
배열에 해당 요소가 들어갈 자리를 이진탐색을 통해 찾고 그 자리에 삽입한다.
arr
배열의 모든 요소가 탐색이 끝나면 dp
배열의 길이를 통해 LIS의 길이를 구할 수 있다.
풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int n;
static int[] arr, dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
arr = new int[n];
dp = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int lis = 0;
for(int i = 0; i < n; i++) {
int index = binarySearch(arr[i], 0, lis, lis+1);
if(index == -1) {
dp[lis++] = arr[i];
}
else {
dp[index] = arr[i];
}
}
System.out.println(lis);
}
public static int binarySearch(int num, int left, int right, int size) {
int res = 0;
while(left <= right) {
int mid = (left + right) / 2;
if(num <= dp[mid]) {
res = mid;
right = mid - 1;
}
else {
left = mid + 1;
}
}
if(left == size) {
return -1;
}
else {
return res;
}
}
}
댓글남기기