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
- TwoPointer
- git
- 다이나믹 프로그래밍
- 네트워크 관리 및 진단
- Linux
- 깃허브
- 투포인터
- network
- RLD
- Prefix sum
- spring
- HTTP/2
- 리눅스
- 알고리즘
- 깃
- 스프링
- Spring Boot
- HTTP/3
- 로그 수집
- 비트마스킹
- SlidingWindow
- 누적합
- Domain Name Space
- github
- 스프링부트
- 네트워크
- 슬라이딩 윈도우
- AppArmor
- bitmasking
- 부팅 장애 대응
Archives
- Today
- Total
kimgusxo 님의 블로그
분할정복(Divide and Conquer) 본문
1. 분할정복(Divide and Conquer)이란?

- 분할정복은 문제를 작은 하위 문제로 분할(Divide)하고 각각을 재귀적으로 해결(Conquer)한 뒤 다시 합쳐(Merge) 전체 문제의 해답을 얻는 알고리즘 기법이다.
- 대표적으로 병합 정렬(Merge Sort), 퀵 정렬(Quick Sort), 큰 수 거듭제곱 문제 등이 있다.
1-1. 핵심 아이디어
- 분할(Divide): 해결하고자 하는 문제를 더 이상 분할할 수 없거나 충분히 작아질 때까지 여러 하위 문제로 나눈다.
- 정복(Conquer): 분할된 하위 문제를 재귀적으로 해결한다.
- 병합(Merge): 각각의 하위 문제에서 구한 해답을 병합하여 원래 문제의 답을 도출한다.
1-2. 장점 및 단점
- 장점: 큰 문제를 여러개의 작은 문제로 나누어 논리적 단순화가 가능, 병렬처리나 캐싱에 유리하다
- 단점: 잘못된 분할 기준 설정 시 재귀 호출이 많아져 효율이 떨어질 수 있다
2. 분할정복 활용 문제
2-1. 병합 정렬(Merge Sort)
- 병합 정렬은 배열을 절반으로 계속 나눈 뒤, 각 하위 배열을 정렬하고 이를 정렬된 상태로 합치는 과정으로 동작한다.
- O(NlogN)의 시간복잡도를 가진다.
public class MergeSort {
public static void merge(int[] arr, int left, int mid, int right) {
// 임시 배열에 병합 결과를 저장
int[] temp = new int[right-left-1];
int i = left;
int j = mid+1;
int k = 0;
// 양쪽 부분 배열을 비교하며 작은 값부터 삽입
while(i <= mid && j <= right) {
if(arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
// 왼쪽 부분에 남은 데이터 삽입
while(i <= mid) {
temp[k++] = arr[i++];
}
// 오른쪽 부분에 남은 데이터 삽입
while(j <= right) {
temp[k++] = arr[j++];
}
// temp 배열의 원소를 다시 arr에 복사
for(int t = 0; t < temp.length; t++) {
arr[left+t] = temp[t];
}
}
public static void mergeSort(int[] arr, int left, int right) {
if(left < right) {
int mid = (left+right)/2;
// Divide: 왼쪽 절반, 오른쪽 절반으로 나눠서 재귀 호출
mergeSort(arr, left, mid);
mergeSort(arr, mid+1, right);
// Combine: 정렬된 두 부분을 병합
merge(arr, left, mid, right);
}
}
public static void main(String[] args) {
// 예제 데이터
int[] arr = {5, 2, 9, 1, 7, 3};
// 병합 정렬 수행
mergeSort(arr, 0, arr.length-1);
// 출력: 1 2 3 5 7 9
for(int num : arr) {
System.out.print(num + " ");
}
}
}
2-2. 퀵 정렬(Quick Sort)
- 퀵 정렬은 배열에서 하나의 기준 원소(pivot)을 정하고 피벗보다 작거나 같은 요소들은 왼쪽, 피벗보다 큰 요소들은 오른쪽으로 배치하여 재귀적으로 정렬한다.
- 평균의 시간복잡도는 O(NlogN), 최악의 시간복잡도는 O(N^2)이다.
public class QuickSort {
// 배열을 분할하여 피벗의 최종 위치를 반환
public static int partition(int[] arr, int left, int right) {
int pivot = arr[right]; // 맨 오른쪽 요소를 피벗으로 선택
int i = left-1; // i: 피벗보다 작거나 같은 요소들의 끝지점
for(int j = left; j < right; j++) {
// 피벗보다 작거나 같은 경우 왼쪽 파티션으로 교환
if(arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i+1];
arr[i+1] = arr[right];
arr[right] = temp;
return i+1;
}
public static void quickSort(int[] arr, int left, int right) {
if(left <= right) {
// Conquer: 파티션 함수로 피벗의 위치를 얻고 왼쪽/오른쪽 각각 정렬
int pivotIndex = partition(arr, left, right);
quickSort(arr, left, pivotIndex-1);
quickSort(arr, pivotIndex+1, right);
}
}
public static void main(String[] args) {
// 예제 데이터
int[] arr = {10, 7, 8, 9, 1, 5};
// 퀵 정렬 수행
quickSort(arr, 0, arr.length-1);
// 출력: 1 5 7 8 9 10
for(int num : arr) {
System.out.print(num + " ");
}
}
}
'Algorithm' 카테고리의 다른 글
다이나믹 프로그래밍(Dynamic Programming) (1) | 2025.05.05 |
---|---|
비트마스킹(Bitmasking) (0) | 2025.04.28 |
백트래킹(Backtracking) (0) | 2025.03.28 |
깊이 우선 탐색(DFS) (0) | 2025.03.22 |
너비 우선 탐색(BFS) (0) | 2025.03.22 |