Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 배열에서 최대 삼중항(Triplet) 합 구하기

이 문제에서는 하나의 배열이 주어지며, 우리의 과제는 배열에서 최대 삼중항 합(maximum triplet sum)을 찾는 프로그램을 작성하는 것입니다. 즉, 세 개의 원소를 골랐을 때 그 합이 가장 커지는 조합을 찾아야 합니다.

문제 이해하기

예시를 통해 문제를 살펴보겠습니다.

입력 − array = {4, 6, 1, 2}

출력 − 12

설명

배열의 모든 삼중항 :
(4, 6, 1) = 4+6+1 = 11
(4, 6, 2) = 4+6+2 = 12
(4, 1, 2) = 4+1+2 = 7
(6, 1, 2) = 6+1+2 = 9
따라서 최대 삼중항 합은 12입니다.

방법 1: 완전 탐색(Brute Force)

가장 단순한 접근 방식은 위 예시에서 확인한 것처럼, 가능한 모든 삼중항 조합의 합을 계산한 뒤 그중 최댓값을 찾는 것입니다. 세 개의 중첩 반복문을 실행하여 모든 삼중항의 합을 구하고, 현재까지의 최대합(maxSum)보다 크면 값을 갱신하는 방식입니다.

하지만 이 방법은 배열의 길이가 길어질수록 삼중항의 개수가 급격히 늘어나므로 비효율적입니다. 시간 복잡도는 O(n³)으로, 입력 크기가 커지면 성능이 크게 저하됩니다.

예제 코드

#include <iostream>
using namespace std;

int maxSum(int arr[], int n){
    int maxSum = 0;
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            for (int k = j + 1; k < n; k++)
                if (maxSum < arr[i] + arr[j] + arr[k])
                    maxSum = arr[i] + arr[j] + arr[k];
    return maxSum;
}

int main(){
    int arr[] = { 3, 5, 7, 1, 9, 0 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "배열의 최대 삼중항 합은 " << maxSum(arr, n);
    return 0;
}

출력

배열의 최대 삼중항 합은 21

방법 2: 정렬 활용 (효율적 접근)

훨씬 효율적인 방법은 배열을 먼저 오름차순으로 정렬한 뒤, 마지막 세 개의 원소(가장 큰 세 값)의 합을 구하는 것입니다. 배열이 정렬되어 있다면 최대 삼중항은 반드시 가장 큰 세 원소로 구성되기 때문입니다. 이 방법의 시간 복잡도는 정렬에 의해 O(n log n)으로 완전 탐색보다 월등히 빠릅니다.

예제 코드

#include <bits/stdc++.h>
using namespace std;

int maxSum(int arr[], int n) {
    sort(arr, arr + n);
    return arr[n - 1] + arr[n - 2] + arr[n - 3];
}

int main() {
    int arr[] = { 3, 5, 9, 1, 2, 8, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "배열의 최대 삼중항 합은 " << maxSum(arr, n);
    return 0;
}

출력

배열의 최대 삼중항 합은 24

참고: 음수가 포함된 경우와 추가 최적화

완전 탐색 코드에서 maxSum을 0으로 초기화하면 배열 전체가 음수일 때 잘못된 결과가 나올 수 있습니다. 이 경우 첫 번째 삼중항의 합 또는 INT_MIN으로 초기화하는 것이 안전합니다.

또한 정렬조차 하지 않고 O(n) 한 번의 순회로 해결할 수도 있습니다. 배열을 한 번만 훑으면서 최댓값, 두 번째 최댓값, 세 번째 최댓값 세 변수를 유지하면 되는데, 이는 정렬 기반 방법보다도 빠른 최적의 해법입니다.