기타/코딩테스트
(코딩테스트) 백준_11053_가장 긴 증가하는 부분 수열 / DP
불광동 물주먹
2025. 5. 24. 17:45
최초 제시한 답 (정답) * 시간 복잡도 = O(N²)
package codingTest;
import java.util.*;
import java.io.*;
public class Backjun_11053_tets {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N=Integer.parseInt(br.readLine());
StringTokenizer st =new StringTokenizer(br.readLine());
int[] list = new int[N];
int[] dp = new int[N];
for(int i =0;i<N;i++) {
list[i] = Integer.parseInt(st.nextToken());
}
for(int i =0;i<N;i++) {
dp[i] = 1; //기본 1값 다 세팅
}
/*
* 6
*
* 10 20 10 30 20 50
*/
// dp 다 채움
for(int i=1;i<N;i++) {
for(int k=0;k<i;k++) {
if(list[k] < list[i]) {
dp[i] = Math.max(dp[i], dp[k]+1);
}
}
}
int max =0;
for(int i =0;i<N;i++) {
max = Math.max(max, dp[i]);
}
System.out.print(max);
}
}
최적화된 답 (정답) * 시간 복잡도 = O(N log N) DP 풀이는 아님.
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
List<Integer> lis = new ArrayList<>();
for (int num : arr) {
int idx = Collections.binarySearch(lis, num);
if (idx < 0) {
idx = -(idx + 1); // 삽입할 위치
}
if (idx == lis.size()) {
lis.add(num); // 새로운 값 추가
} else {
lis.set(idx, num); // 더 작은 값으로 교체
}
}
System.out.println(lis.size()); // LIS 길이
}
}
느낀점
이중 for 로 시간복잡도 N2를 사용하지 않고
컬렉션 arraylist에 차례로 값을 담아 마지막에 list 길이로 결과 값 출력한다는게 인상 깊었다.
처음 어려웠던점.
1. binarySearch + set으로 기존 값 교체
- binarySearch는 list 안에 정수 값이 들어가야할 위치를 리턴 시켜주는데
키 값이 존재하면 양수로 위치 index
키 값이 존재하지 않는다면 음수로 위치 index-1 값 해준다 (그래서 양수 전환시 ( - index)+1 이 필요하다. )
그 후 if문에서 인덱스의 길이와 list의 길이를 비교하여 뒤에 들어올 값이면 add로 뒤에 저장
만약 중간에 값 교체라면 set으로 값 교체 (처음 이 부분이 이해가 안갔다. 기존 값을 버리고? 신규 값 교체??? 삭제될 값이 크면 굳이 버릴 필요가 없지 않나라고 생각했으나 문제에서는 수열이라 순서를 지켜야하기에 뒤에 올 값이 크든말든 set 될 값이 더 작다면 다음 들어올 값의 허용되는 부분이 더 늘어나기에 작은 값으로 교체 해주는게 확률적으로 더 이득이라 기존의 큰 값은 삭제가 맞다..... )