본문 바로가기
IT/알고리즘

분할 정복 : 작은 부분에서 얻는 큰 지혜

by goodchuck 2024. 5. 6.

 

안녕하세요! goodchuck 입니다!

블로그에 방문해주셔서 감사합니다!

 

 1. 분할 정복 알고리즘의 탄생 배경

분할 정복 알고리즘은 1960년대 컴퓨터 과학자들이 복잡한 문제를 해결하기 위해 고안한 기법입니다. 당시 컴퓨터의 성능이 낮아서 큰 문제를 한 번에 해결하기 어려웠던 것이 계기가 되었습니다. 이에 문제를 작은 부분으로 나누어 각각 해결한 뒤, 그 결과를 합치는 방식으로 접근하게 되었습니다.

 

 2. 분할 정복 알고리즘이란?

분할 정복 알고리즘은 큰 문제를 작은 부분 문제로 나누어 각각을 해결한 다음, 그 해답을 모아서 전체 문제를 해결하는 알고리즘 설계 패러다임입니다. 이 기법은 재귀적인 방식으로 동작하며, 높은 효율성을 가지고 있습니다.

 

 3. 분할 정복 알고리즘의 일반적인 절차

1. **분할(Divide)**: 문제를 작은 부분 문제들로 나눈다.

2. **정복(Conquer)**: 나눈 부분 문제들을 각각 해결한다.

3. **결합(Combine)**: 부분 문제의 해답을 모아 전체 문제의 해답을 구한다.

 

 4. 분할 정복 알고리즘의 예시

4.1 병합 정렬(Merge Sort)

병합 정렬은 대표적인 분할 정복 알고리즘 기반의 정렬 알고리즘입니다.

1. 분할: 배열을 절반으로 나눈다.

2. 정복: 나눈 배열을 재귀적으로 정렬한다.

3. 결합: 정렬된 배열을 병합하여 전체를 정렬한다.

 

4.2 퀵 정렬(Quick Sort)

퀵 정렬 또한 분할 정복 기법을 사용하는 정렬 알고리즘입니다.

1. 분할: 피벗을 기준으로 배열을 두 부분으로 나눈다.

2. 정복: 피벗을 제외한 왼쪽 부분과 오른쪽 부분을 재귀적으로 정렬한다.

3. 결합: 정렬된 왼쪽 부분, 피벗, 정렬된 오른쪽 부분을 연결한다.

 

4.3 스트라센 알고리즘(Strassen Algorithm)

스트라센 알고리즘은 두 행렬의 곱셈을 분할 정복 방식으로 효율적으로 계산하는 알고리즘입니다.

1. 분할: 두 행렬을 작은 부분 행렬로 나눈다.

2. 정복: 부분 행렬들의 곱셈을 재귀적으로 계산한다.

3. 결합: 부분 행렬의 곱셈 결과를 모아 전체 행렬의 곱셈 결과를 얻는다.

 

 5. 분할 정복 알고리즘의 시간 복잡도

분할 정복 알고리즘의 시간 복잡도는 문제의 크기에 따라 달라집니다. 일반적으로 다음과 같은 재귀 관계식을 가집니다.

 

T(n) = aT(n/b) + f(n)

 

여기서 a는 분할되는 부분 문제의 개수, n/b는 부분 문제의 크기, f(n)은 분할과 결합에 드는 시간 복잡도입니다.

 

예를 들어, 병합 정렬의 경우 T(n) = 2T(n/2) + O(n)이 됩니다. 이를 풀면 O(n log n)의 시간 복잡도를 가지게 됩니다.

 

 6. 분할 정복 알고리즘의 활용

분할 정복 알고리즘은 다음과 같은 다양한 영역에서 활용됩니다.

 

- 정렬 알고리즘: 병합 정렬, 퀵 정렬 등

- 검색 알고리즘: 이진 검색 등

- 곱셈 알고리즘: 스트라센 알고리즘, 카라츠바 알고리즘 등

- 행렬 계산

- 컨벡스 허ル(Convex Hull) 문제

- closest pair 문제

- 기하 문제

- 동적 계획법 문제

- 그래프 알고리즘: 최소 비용 신장 트리 등

 

 7. 유사 알고리즘과의 비교

7.1 동적 계획법(Dynamic Programming)

동적 계획법은 부분 문제의 중복 계산을 방지하기 위해 부분 문제의 해답을 메모리에 저장하는 기법입니다. 분할 정복 알고리즘과 마찬가지로 부분 문제로 나누어 해결하지만, 동적 계획법은 상향식(bottom-up)으로 접근하는 반면 분할 정복 알고리즘은 하향식(top-down)으로 접근합니다.

 

7.2 그리디 알고리즘(Greedy Algorithm)

그리디 알고리즘은 현재 상황에서 가장 최적의 선택을 하는 방식으로 문제를 해결합니다. 분할 정복 알고리즘과 달리 전체 문제를 부분 문제로 나누지 않고, 각 단계에서 가장 좋은 선택을 하면서 해답을 구성해 나갑니다.

 

 8. 분할 정복 알고리즘의 장단점

8.1 장점

- 많은 경우에 효율적인 시간 복잡도를 가진다.

- 문제를 작은 부분으로 나누어 해결하므로 구현이 간단할 수 있다.

- 병렬 처리에 적합하다.

 

8.2 단점

- 모든 문제가 분할 정복 방식에 적합한 것은 아니다.

- 잘못된 분할 방식은 오히려 비효율적일 수 있다.

- 재귀 호출에 따른 오버헤드가 발생할 수 있다.

- 분할 정복 알고리즘은 일부 문제에 대해 비효율적일 수 있다. 예를 들어 퀵정렬의 경우 이미 정렬된 리스트에 대해서는 O(n^2)의 시간 복잡도를 가진다.

 

 Node.js 구현 코드

 

// 합계 계산을 위한 분할 정복 알고리즘

function sum(arr) {

  // 기저 사례: 배열의 길이가 1 이하이면 그대로 반환

  if (arr.length <= 1) {

    return arr[0] || 0;

  }



  // 분할 단계: 배열을 두 부분으로 나눔

  const mid = Math.floor(arr.length / 2);

  const left = arr.slice(0, mid);

  const right = arr.slice(mid);



  // 정복 단계: 부분 배열의 합계를 재귀적으로 계산

  const leftSum = sum(left);

  const rightSum = sum(right);



  // 결합 단계: 부분 배열의 합계를 모아 전체 합계를 계산

  return leftSum + rightSum;

}



// 사용 예시

const arr = [1, 3, 5, 7, 9];

const result = sum(arr);

console.log(result); // 출력: 25

 

정리하면, 분할 정복 알고리즘은 주어진 문제를 올바르게 분할하고, 부분 문제의 해답을 효율적으로 결합할 수 있을 때 큰 이점을 가질 수 있습니다. 하지만 모든 문제에 최선은 아니며, 때로는 다른 기법이 더 좋은 성능을 보일 수 있습니다. 따라서 문제의 특성을 파악하고 적절한 알고리즘 기법을 선택하는 것이 중요합니다.

 

#알고리즘 #분할정복알고리즘 #알고리즘설계기법 #병렬알고리즘 #재귀알고리즘

 

이상 글 읽어주셔서 감사합니다 다음에도 또 뵐수있길 빌겠습니다!