Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 1300번
- BOJ
- 클린코드
- Design Patterns
- Dxerr.h
- 2166번
- 냄새와 휴리스틱
- programmers
- java의 정석
- 11758번
- DxTrace
- 11286번
- Design Pattern
- 백준
- 2156번
- SerialDate 리펙터링
- 2206번
- 1043번
- 10830번
- Spring
- 자바의 정석
- Adapater Pattern
- springboot
- 코딩 테스트
- 17장
- 프로그래머스
- 코딩테스트
- 9장
- 가장 긴 증가하는 부분 수열2
- java
Archives
- Today
- Total
Don't give up!
[백준] 12015번 : 가장 긴 증가하는 부분 수열 2 (java) 본문
12015번: 가장 긴 증가하는 부분 수열 2 (acmicpc.net)
어떻게 생각하고 문제를 풀었는가?
주어진 수열에서 부분 수열의 원소들이 인덱스가 증가함에 따라 값도 증가함을 만족한다면 증가하는 부분 수열이 될 수 있습니다.
첫번째 인덱스부터 탐색을 시작하여 부분 수열을 형성하고, 마지막 원소보다 작은 값이 발견되었을 경우 부분 수열을 새로 형성하거나, 해당 원소를 무시하고 다음 원소를 탐색하여 부분 수열에 추가함으로써 가장 긴 증가하는 부분 수열을 찾을 수 있습니다.
결과적으로 반환해야 하는 것은 부분 수열의 최대 길이이므로 부분 수열의 원소를 작은 값으로 갱신함으로써 길이만을 보존하고 답을 찾을 수 있을 것이라고 생각하였습니다.
코드
import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
class Main {
private static final ArrayList<Integer> sequence = new ArrayList<>();
public static void main(String[] args) throws IOException {
readInput();
System.out.println(sequence.size()-1);
}
private static void readInput() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
sequence.add(0);
for(int i=0; i<n; i++){
int num = Integer.parseInt(tokenizer.nextToken());
if(num > sequence.get(sequence.size()-1)){
sequence.add(num);
}else{
int index = lowerBound(num);
sequence.set(index, num);
}
}
reader.close();
}
private static int lowerBound(int target){
int left = 1;
int right = sequence.size()-1;
int result = 0;
while(left < right){
int mid = (left+right)/2;
if(sequence.get(mid) >= target){
result = mid;
right = mid-1;
}else{
left = mid+1;
}
}
return result;
}
}
이분 탐색을 사용하여 부분 수열의 최대 길이를 찾는 코드를 작성하였습니다.
O(n)의 탐색으로는 최대 1,000,000 크기의 수열로부터 부분 수열을 찾을 수 없기 때문에 이분탐색을 이용하여 O(nlogn)으로 탐색 시간을 줄일 수 있습니다.
각 인덱스를 탐색하여 부분 수열에 원소를 추가하고, 추가하려는 원소가 부분 수열의 마지막 값보다 작은 값을 갖는 경우 해당 값보다 작거나 같은 가장 큰 원소를 이분 탐색으로 찾고, 해당 원소와 바꾸도록 함으로써 새로운 부분 수열을 형성합니다.
이후 마지막 원소보다 큰 값을 갖는 원소가 추가될 경우 부분 수열에 추가됨으로써 기존 부분 수열의 최대 길이를 찾을 수 있습니다.
'Coding Test > BOJ' 카테고리의 다른 글
[백준] 1655번 : 가운데를 말해요 (java) (0) | 2021.08.22 |
---|---|
[백준] 1300번 : K번째 수 (java) (0) | 2021.08.20 |
[백준] 10830번 : 행렬 제곱 (java) (0) | 2021.08.18 |