이 문제에서는 정수로 이루어진 배열 arr[]가 주어지며, C++를 사용해 두 번의 순회(Two Traversals) 방식으로 최대 곱 부분 배열(Maximum Product Subarray)을 찾는 프로그램을 작성하는 것이 목표입니다.
문제 설명
주어진 배열에서 인덱스 0부터 시작하는 순회(왼쪽 → 오른쪽)와 인덱스 n-1부터 시작하는 순회(오른쪽 → 왼쪽), 총 두 번의 순회를 이용해 곱이 가장 큰 부분 배열의 값을 구합니다.
예제로 문제 이해하기
입력
arr[] = {4, -2, 5, -6, 0, 8}출력
240
설명
부분 배열 = {4, -2, 5, -6}
최대 곱 = 4 * (-2) * 5 * (-6) = 240음수가 두 개 포함되어 있어 서로 곱해지면 양수가 되고, 여기에 0은 곱셈에 영향을 주지 않도록 처리하면 위와 같이 최댓값 240을 얻을 수 있습니다.
해결 접근 방법
두 번의 순회를 활용하는 방식은 다음과 같습니다.
1. 왼쪽 → 오른쪽 순회: 인덱스 0부터 n-1까지 배열을 순회하며 각 요소를 누적 곱에 곱해 나갑니다.
2. 오른쪽 → 왼쪽 순회: 인덱스 n-1부터 0까지 반대 방향으로 순회하며 같은 방식으로 누적 곱을 계산합니다.
순회 중 누적 곱이 0이 되면, 이후 곱셈 결과가 모두 0으로 고정되는 것을 막기 위해 값을 1로 초기화합니다. 마지막으로 두 방향에서 얻은 최댓값 중 더 큰 값을 정답으로 반환합니다.
C++ 구현 코드
#include<iostream>
using namespace std;
int CalcMaxProductSubArray(int arr[], int n) {
int frntMax = 1, rearMax = 1, maxVal = 1;
for (int i=0; i<n; i++) {
frntMax = frntMax*arr[i];
if (frntMax == 0)
frntMax = 1;
}
for (int i=n-1; i>=0; i--) {
rearMax = rearMax * arr[i];
if (rearMax == 0)
rearMax = 1;
}
maxVal = max(frntMax, rearMax);
return maxVal;
}
int main() {
int arr[] = {4, -2, 5, -6, 0, 8};
int n = sizeof(arr)/sizeof(arr[0]);
cout<<"Maximum product subarray is "<<CalcMaxProductSubArray(arr, n);
return 0;
}실행 결과
Maximum product subarray is 240
시간 복잡도
배열을 앞뒤로 각각 한 번씩 순회하므로 시간 복잡도는 O(n)이며, 추가적인 저장 공간 없이 몇 개의 변수만 사용하므로 공간 복잡도는 O(1)입니다.