728x90
어제 오늘은 이진탐색 부수기를 하고 있다.
드디어 백준 단계별로 풀기에서 이진탐색을 밀었다!
이진 탐색에 대해서 심리적 거부감이 있던 터라 극복하면 보이지 않는 벽을 부순다는 일념으로 열심히 도전했다.
이진 탐색은 결국 매개변수 탐색과 연결된다는 점이 핵심인 것 같다.
풀이는 List 활용 방식과 Array(배열) 탐색 방식이며 Array방식이 시간이 더 짧다. ( 756ms[List] > 592ms[Array])
<문제 접근/풀이 방식>
1. 이진탐색(매개변수 탐색)을 사용하기 위해서는 다음 두 가지 조건이 필요하다.
1.1 순차대로 탐색이 가능해야한다.
1.2 특정 단절점이 있어야 한다.
2. 거진 반나절을 꼬박 생각해도 특정 위 두 가지 조건에 맞추는 방법을 생각지 못해서 구글링을 했더니 list 풀이 방식이 나왔다.
3. List는 남의 접근법이므로 배열로 풀어야 내가 실전에서 쓸 수 있을 것 같아서 배열로 풀어보았다.
4. 풀이는 다음과 같다.(배열 풀이로 설명 -> 본인이 직접 푼 풀이에 해당하므로)
5 10 15 1 2 3이라는 값이 들어 왔을 때, 배열은 +1만큼 패딩해서 [0, 0, 0, 0, 0, 0, 0](7개의 배열 선언), lastIndex = 1인 상황
5 입력
lastIndex = 1이므로 배열의 lastIndex-1 번째 값과 비교해보니 5가 더 커서 lastIndex에 값을 넣고 index++;
배열 값 : [0, 5, 0, 0, 0, 0, 0] / lastIndex = 2
10 입력
lastIndex = 2임로 배열의 lastIndex-1 번째 값과 비교해보니 10이 더 커서 위와 동일하게 적용
배열 값 : [0, 5, 10, 0, 0, 0, 0] / lastIndex = 3
15 입력
위와 동일
배열 값 : [0, 5, 10, 15, 0, 0, 0] / lastIndex = 4
1 입력
lastIndex-1 번째 값과 비교 해보니 1이 더 작아서 이진탐색을 통해 1이 들어갈 인덱스 탐색
index 1번째에 들어갈 수 있음
배열 값 : [0, 1, 10, 15, 0, 0, 0] / lastIndex = 4
2 입력
위와 동일한 과정 거쳐서
배열 값 : [0, 1, 2, 15, 0, 0, 0] / lastIndex = 4
3 입력
위와 동일한 과정 거쳐서
배열 값 : [0, 1, 2, 3, 0, 0, 0] / lastIndex = 4
답은 lastIndex -1을 출력하면 된다.
소스코드를 보면 더 이해가 쉬울 것이다. 우리는 개발자니까!
<List를 활용한 소스코드>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Main {
static List<Integer> answer;
public static void main(String[] args) throws IOException {
// 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)
// Ai (1 ≤ Ai ≤ 1,000,000)
// NlogN의 시간 복잡도를 가져야 함
// 10 20 10 30 20 50
// 1 2 1 3 2 4
// 이진탐색을 활용해서 풀어보자
// 단절이 발생하는가
// 1. 특정 수를 선택
// 2. 그 수 보다 낮으면서 누적 횟수가 가장 많은 경우 + 1
// 3. 단절성이 있어야 함, 순서대로 탐색을 해도 무방해야 함.
// 10 20 10 15 20 30 30 50
// 1 2 1 2 3 4 4 5
// 1 : 10, 10
// 2 : 15, 20
// 3 : 20
// 4 : 30, 30
// 5 : 50
// 10 20 1 2 3 4
// 0, 10
// 0, 10, 20
// 0, 1, 20
// 0, 1, 2
// 0, 1, 2
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int arr[] = new int[N];
answer = new ArrayList<>();
// list 패딩
answer.add(0);
String[] temp = br.readLine().split(" ");
for (int i = 0; i < arr.length; i++) {
int value = Integer.parseInt(temp[i]);
// 만든 수열의 가장 큰 값보다 클 경우 뒤에 add
if(answer.get(answer.size()-1) < value) {
answer.add(value);
continue;
}
int s = 0;
int e = answer.size() - 1;
int index = 0;
while(s <= e) {
int mid = (s + e) >> 1;
if(check(mid, value)) {
index = mid;
e = mid - 1;
}else {
s = mid + 1;
}
}
answer.set(index, value);
}
System.out.println(answer.size()-1);
}
private static boolean check(int mid, int value) {
return answer.get(mid) >= value;
}
}
<배열을 활용한 소스코드>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Main {
static int[] answer;
public static void main(String[] args) throws IOException {
// 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)
// Ai (1 ≤ Ai ≤ 1,000,000)
// NlogN의 시간 복잡도를 가져야 함
// 10 20 10 30 20 50
// 1 2 1 3 2 4
// 이진탐색을 활용해서 풀어보자
// 단절이 발생하는가
// 1. 특정 수를 선택
// 2. 그 수 보다 낮으면서 누적 횟수가 가장 많은 경우 + 1
// 3. 단절성이 있어야 함, 순서대로 탐색을 해도 무방해야 함.
// 10 20 10 15 20 30 30 50
// 1 2 1 2 3 4 4 5
// 1 : 10, 10
// 2 : 15, 20
// 3 : 20
// 4 : 30, 30
// 5 : 50
// 10 20 1 2 3 4
// 0, 10
// 0, 10, 20
// 0, 1, 20
// 0, 1, 2
// 0, 1, 2
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
answer = new int[N+1];
// list 패딩
String[] temp = br.readLine().split(" ");
int lastIndex = 1;
for (int i = 0; i < N; i++) {
int value = Integer.parseInt(temp[i]);
// 만든 수열의 가장 큰 값보다 클 경우 뒤에 add
if(answer[lastIndex-1] < value) {
answer[lastIndex++] = value;
continue;
}
int s = 0;
int e = lastIndex-1;
int index = 0;
while(s <= e) {
int mid = (s + e) >> 1;
if(check(mid, value)) {
index = mid;
e = mid - 1;
}else {
s = mid + 1;
}
}
answer[index] = value;
}
System.out.println(lastIndex-1);
}
private static boolean check(int mid, int value) {
return answer[mid] >= value;
}
}
728x90
'알고리즘공부(Algorithm Study) > 문제풀이(ProblemSolving)' 카테고리의 다른 글
백준 7569 java - 토마토(그래프/bfs) (0) | 2022.05.30 |
---|---|
백준 1637 java - 날카로운 눈(이진탐색, 누적합, 정수론/feat.생애첫플레 1솔) (0) | 2022.05.29 |
백준 24444 & 24445 알고리즘 수업 - 너비 우선 탐색1 & 너비우선 탐색 2 (0) | 2022.05.28 |
백준 24479 & 24480 알고리즘 수업 - 깊이 우선 탐색 1&2(DFS) (0) | 2022.05.24 |
백준 1520 java - 내리막길(DP, 동적계획법) (0) | 2022.05.23 |
댓글