본문 바로가기

PS/기타

[알고리즘]배열의 부분 최대합

반응형
[알고리즘]배열의 부분 최대합

[알고리즘]배열의 부분 최대합

주어진 배열에서 연속된 구간 중 합이 최대가 되는 곳을 찾는 문제이다.

배열

다음과 같이 재열이 주어졌을 때, 2 ~ 4 구간의 합이 11로 최대값을 가진다. 이를 찾기 위한 첫 번째 방법은 배열을 순회하며 모든 구간의 합을 구하여 최대값을 찾는 것이다. 이를 코드로 표현하면 다음과 같다.

코드를 살펴보면 0부터 시작하여 모든 부분합을 확인하기 위해 for문을 이중으로 순회한다. 따라서 이 방법을 사용하면 O(n^2)의 시간 복잡도를 가지게 된다. 이 경우 배열의 크기가 매우 커진다면 값을 구하는 데 오랜 시간이 걸린다. 이것보다 빠르게 구하기 위한 방법으로 분할정복을 적용할 수 있다.

분할정복 알고리즘이란 주어진 문제를 작은 부분으로 분할하여 해결하여 답을 얻는 알고리즘이다. 이 문제에 분할정복 알고리즘을 적용하기 위해 부분합이 어떤 경우에 존재하는지 생각해보자.

첫 째로 주어진 배열의 중앙부터 최대가 되는 부분합을 구한다. 그리고 배열을 절반으로 나누어 왼쪽 부분의 최대합과 오른쪽 부분의 최대합을 구한다. 그리고 이렇게 구한 세 값(중앙에 걸친 값, 왼쪽 값, 오른쪽 값) 중 최대가 되는 값을 가져오면 된다. 왼쪽의 값과 오른쪽의 값을 구하기 위해 배열을 나누고 이를 반복하면 결국 전체 배열의 부분 최대합을 구할 수 있다. 답을 구하기 위해 배열을 둘로 나누는 작업을 반복한다. 이 과정을 그림으로 나타내면 다음과 같다.

 

분할

배열을 절반씩 나누는데는 logN만큼 소요된다. 따라서 분할정복을 통해 부분 최대합을 구하면 O(NlogN)의 시간 복잡도를 가진다. 이를 코드로 나타내면 다음과 같다.

먼저 배열의 중간에 걸친 최대합을 구한 뒤 재귀호출을 통해 왼쪽 부분과 오른쪽 부분을 나누어 부분 합을 구한다. 재귀 호출을 하면 해당 부분 배열에 대해 위 과정을 반복하고 최대값을 리턴한다. 만일 나누어진 부분의 크기가 1이라면 그 값만 리턴한다.

DP를 이용하면 이보다 더 빠르게 부분합을 구할 수 있는 방법이 있다. 한 번의 순회를 통해 최대값을 구하기 때문에 O(N)의 시간복잡도를 가진다. 배열을 순회하며 값을 하나씩 더하여 부분합을 구한다. 만일 부분합이 0보다 작다면 이전의 부분합은 무시하고 새로 추가된 값으로 갱신한다. 이렇게 구한 부분합들 중 최대가 되는 값을 찾는것이다. 이를 코드로 나타내면 다음과 같다.

 

위의 코드들을 10,000개 원소를 가진 배열로 측정한 결과는 다음과 같다.

결과

반응형

'PS > 기타' 카테고리의 다른 글

Overlapped Model  (0) 2019.06.03