Algorithm, Data structure/Popular Algorithms

Maximum subarray problem

JaykayChoi 2016. 6. 3. 01:00

In computer science, the maximum subarray problem is the task of finding the contiguous subarray within a one-dimensional array of numbers which has the largest sum. For example, for the sequence of values −2, 1, −3, 4, −1, 2, 1, −5, 4; the contiguous subarray with the largest sum is 4, −1, 2, 1, with sum 6.

The problem was first posed by Ulf Grenander of Brown University in 1977, as a simplified model for maximum likelihood estimation of patterns in digitized images. A linear time algorithm was found soon afterwards by Jay Kadane of Carnegie-Mellon University (Bentley 1984).


출처: https://en.wikipedia.org/wiki/Maximum_subarray_problem



분할 정복과 동적 계획법을 공부할 수 있는 Maximum subarray problem (최대 구간 합 문제) 입니다.


분할 정복 풀이법은 배열을 절반으로 나눠서 좌측 부분의 최대합과 우측 부분의 최대합의 합과 그리고 정답(최대합)의 배열이 (좌측이나 우측) 한 쪽에서 시작해서 한 쪽에서 끝날 가능성을 고려하여 3가지 경우 중 최대값을 구하는 방법입니다. 


동적 계획 풀이법은 동적 계획법답게 중복해서 최소값을 구하는 부분 즉 계산할 필요가 없는 부분을 건너뛰어 (계산 결과를 재활용함으로써) 시간 복잡도를 줄이고 있습니다.



c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <vector>
#include <ctime>
 
using namespace std;
 
vector<int> numbers;
int N;
 
 
int bruteForce()
{
    int ret = INT_MIN;
    for (int i = 0; i < N; i++)
    {
        int sum = 0;
        for (int j = i; j < N; j++)
        {
            sum += numbers[j];
            ret = max(ret, sum);
        }
    }
    return ret;
}
 
int divideAndConquer(int left, int right)
{
    if (left == right)
        return numbers[left];
 
    int leftMaxSum = INT_MIN;
    int rightMaxSum = INT_MIN;
    
    int middle = (left + right) / 2;
 
    int tempSum = 0;
    for (int i = middle; i >= left; i--)
    {
        tempSum += numbers[i];
        leftMaxSum = max(leftMaxSum, tempSum);
    }
    tempSum = 0;
    for (int i = middle + 1; i <= right; i++)
    {
        tempSum += numbers[i];
        rightMaxSum = max(rightMaxSum, tempSum);
    }
 
    int dividedMaxSum = max(divideAndConquer(left, middle), divideAndConquer(middle + 1, right));
 
    return max(leftMaxSum + rightMaxSum, dividedMaxSum);
}
 
//Kadane's algorithm
int dynamicProgramming()
{
    int ret = INT_MIN;
    int partialSum = 0;
 
    for (int i = 0; i < N; i++)
    {
        partialSum = max(partialSum, 0+ numbers[i];
        ret = max(partialSum, ret);
    }
 
    return ret;
}
 
int main() 
{
    //8000 numbers 
    ifstream fin("input.in");
 
    int a;
    while (fin >> a)
    {
        numbers.push_back(a);
    }
 
    N = numbers.size();
 
 
    clock_t start = clock();
 
    cout << "bruteForce : " <<  bruteForce() << " elapse time : ";
 
    clock_t end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    cout << time << endl;
 
 
 
    start = clock();
 
    cout << "divideAndConquer : " << divideAndConquer(0, N - 1<< elapse time : ";
 
    end = clock();
    time = double(end - start) / CLOCKS_PER_SEC;
    cout << time << endl;
 
 
 
    start = clock();
 
    cout << "dynamicProgramming : " << dynamicProgramming() << elapse time : ";
 
    end = clock();
    time = double(end - start) / CLOCKS_PER_SEC;
    cout << time << endl;
 
 
    system("pause");
    return 0;
}
 
 
cs





bruteForce : 1646 elapse time : 11.554

divideAndConquer : 1646 elapse time : 0.041

dynamicProgramming : 1646 elapse time : 0.004




'Algorithm, Data structure > Popular Algorithms' 카테고리의 다른 글

karatsuba algorithm  (0) 2016.06.21
Travelling salesman problem  (0) 2016.06.05