분할 정복 알고리즘

개요[편집 / 원본 편집]

주어진 문제를 작은 사례로 나누고(Divide), 각각의 작은 문제들을 해결하여 정복(Conquer)하는 방법이다. 분할 정복법은 문제의 사례를 2개 이상의 더 작은 사례로 나눈다. 이 작은 사례는 주로 원래 문제에서 따온다. 나눈 작은 사례의 해답을 바로 얻을 수 있으면 해를 구하고 아니면 더 작은 사례로 나눈다.

해를 구할 수 있을 만큼 충분히 더 작은 사례로 나누어 해결하는 방법이다.

분할 정복법은 하향식(top-down) 접근 방법으로 최상위 사례의 해답은 아래로 내려가면서 작은 사례에 대한 해답을 구함으로써 구한다.

설계전략[편집 / 원본 편집]

  1. 문제 사례를 하나 이상의 작은 사례로 분할(Divide)한다.
  2. 작은 사례들을 각각 정복(Conquer)한다. 작은 사례가 충분히 작지 않은 이상 재귀를 사용한다.
  3. 필요하다면, 작은 사례에 대한 해답을 통합(Combine)하여 원래 사례의 해답을 구한다.

분할 정복 사용 예[편집 / 원본 편집]

  • 이분검색
  • 합병정렬
  • 퀵정렬
  • 최대값 찾기
  • 임계값의 결정
  • 쉬트라센 행렬곱셈 알고리즘 등

이분검색[편집 / 원본 편집]

문제 : 10개의 정렬된 배열에서 값을 21가진 인덱스를 찾아라.

low: 0
high: 9
middle: (low + high)/2 => 4.5 => 4
A(0) A(1) A(2) A(3) A(4) A(5) A(6) A(7) A(8) A(9)
5 7 10 12 16 20 21 25 28 30


low: 4 + 1 => 5
high: 9
middle: 7
A(0) A(1) A(2) A(3) A(4) A(5) A(6) A(7) A(8) A(9)
5 7 10 12 16 20 21 25 28 30


low: 5
high: 7 - 1 = 6
middle: 5
A(0) A(1) A(2) A(3) A(4) A(5) A(6) A(7) A(8) A(9)
5 7 10 12 16 20 21 25 28 30


low: 5 + 1 = 6
high: 6
A(0) A(1) A(2) A(3) A(4) A(5) A(6) A(7) A(8) A(9)
5 7 10 12 16 20 21 25 28 30


int[] arr = {5, 7, 10, 12, 16, 20, 21, 25, 28, 30}

public int binarySearch(int target) {
    low = 0;
    high = arr.length;
    while (low <= high) {
		middle = (low + high) / 2;
		if (target == array[middle]) {
			return middle;
		} else if (target > array[middle]) {
			low = middle + 1;
		} else {
			high = middle - 1;
		}
	}
    return -1; //not found
}

장단점[편집 / 원본 편집]

장점[편집 / 원본 편집]

  • 문제를 나눔으로써 어려운 문제를 해결할 수 있다는 엄청나게 중요한 장점이 있다.
  • 이 방식이 그대로 사용되는 효율적인 알고리즘들도 여럿 있으며, 문제를 나누어 해결한다는 특징상 병렬적으로 문제를 해결하는 데 큰 강점이 있다.

단점[편집 / 원본 편집]

  • 함수를 재귀적으로 호출한다는 점에서 함수 호출로 인한 오버헤드가 발생한다.
  • 스택에 다양한 데이터를 보관하고 있어야 하므로 스택 오버플로우가 발생하거나 과도한 메모리 사용을 하게 된다.

CC BY로 가져옴

• 현재 페이지 URL 줄이기