[개념 학습 및 정리] 분할 정복법
2021. 1. 28. 16:05ㆍ코딩 테스트/개념 학습 및 정리
1. 분할 정복법
분할 정복법은 거의 대부분 재귀호출을 이용하여 해결하는 경우가 많다.
- 문제를 소문제로 분할 (합병 정렬, 퀵 정렬)
- 각각의 소문제를 해결
- 소문제의 해결 결과를 이용하여 전체 문제를 해결
2. 연속 부분 최대합
연속된 부분을 선택하여 그 합이 최대가 되게 하는 방법 (단, n은 1이상 100000이하)
2 | 1 | -2 | 5 | -10 | 3 | 2 | 5 | -3 | 7 | 9 | -10 |
문제 이해)
- 완전 탐색법으로 가능한 모든 경우의 수를 고려, 전체 시간은 O(n^3) 걸리기에 완전 탐색법은 불가능
- 분할 정복법으로 접근
알고리즘 개발)
우선 절반으로 나누어 각 소문제의 최대합을 찾아서 문제를 해결한다.
[소문제 1] 최대합은 6
2 | 1 | -2 | 5 | -10 | 3 |
[소문제 2] 최대합은 20
2 | 5 | -3 | 7 | 9 | -10 |
[자른 지점을 포함하는 부분]
자른 지점을 포함하는 연속 부분의 최대합을 고려해야한다. 자른 지점을 기준으로 왼쪽의 최대값과 오른쪽의 최대값의 합이 자른 지점의 최대값이다.
마지막으로 왼쪽만 포함하는 경우(6)와 오른쪽만 포함하는 경우(20), 자른 자리를 포함하는 경우(23) 중 가장 최대값이 답이다.
알고리즘 증명) 모든 경우(왼쪽, 오른쪽, 자른 지점)를 고려
알고리즘 시간복잡도)
- T(n)은 N개의 숫자 중 연속 부분 최대합을 구하는데 걸리는 시간
- 왼쪽 T(n/2)
- 오른쪽 T(n/2)
- 자른지점 기준 왼쪽, 오른쪽 각각 O(n)
- T(n) = T(n/2) + T(n/2) + O(n)
- T(n) = 2T(n/2) + O(n)
- 즉, 시간복잡도는 O(n logn)
코드 작성)
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static int n;
static int[] data;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
data = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i < n; i++) {
data[i] = Integer.parseInt(st.nextToken());
}
System.out.println(getSubMax(0, n-1));
bw.flush();
bw.close();
br.close();
}
static int getSubMax(int s, int e) {
if(s == e) return data[s];
else {
int mid = (s+e)/2;
int left = getSubMax(s, mid); // 왼쪽 부분의 최대합
int right = getSubMax(mid+1, e); // 오른쪽 부분의 최대합
int leftMax = -987987987;
int leftSum = data[mid];
for(int i = mid-1; i >= 0; i--) {
leftSum += data[i];
if(leftMax < leftSum) leftMax = leftSum;
}
int rightMax = -987987987;
int rightSum = 0;
for(int i = mid+1; i <= e; i++) {
rightSum += data[i];
if(rightMax < rightSum) rightMax = rightSum;
}
int midMax = leftMax + rightMax;
return Math.max(Math.max(left, right), midMax);
}
}
}
/*
예제 입력
12
2 1 -2 5 -10 3 2 5 -3 7 9 -10
예제 출력
23
*/
728x90
'코딩 테스트 > 개념 학습 및 정리' 카테고리의 다른 글
[개념 학습 및 정리] 그래프 (0) | 2021.02.01 |
---|---|
[개념 학습 및 정리] 동적 계획법 (0) | 2021.02.01 |
[개념 학습 및 정리] 문제 해결 (0) | 2021.01.28 |
[개념 학습 및 정리] 자료구조 (0) | 2021.01.25 |