[ISSUE] Maximal Difference

Describe

Given one integer array, you have to find out two disjoint continuous sub-array A and B, which maximate the absolute value of SUM(A)-SUM(B).

For example, [2,-1,-2,1,-4,2,8], A=[-1,-2,1,-4], B=[2,8], the maximum is 16.

Resolve

It’s obvious see that to one array with N length, there is N-1 positions to seperate the original array. Then we get left sub-array and right sub-array.

We have to iterate the left and right part and find out the minimum and maximum respectively using dynamic programming method. It’s important to figure out that, in front of one number position x, the minimum VAL will be VAL[x] = MIN { VAL[x-1]+arr[x], arr[x] } (similar to maximum). Then we could get several minimal (or maximal) sumary value (different end positions) if we notice to mark in all the minimal (or maximal) sumary in all positions.

This algorithm will get O(N) time complexity.

Code

#include <iostream>
using std::cout;
using std::endl;

const int arr[] = {2,-1,-2,1,-4,2,8};
const int sz = sizeof(arr)/sizeof(int);

struct sumType {
    int sum; // the sumary number
    int len; // the length of sumary
    int idx; // the best index in the history
};

// columns represent min & max
sumType left[sz][2];
sumType right[sz][2];

// a: cols in array; b: left or right part
void init(sumType sav[][2], int a, int b) {
    for (int i=b; i<sz-(1-b); ++i) {
        sumType &s = sav[i][a];
        if (i==0) {
            s = {arr[i], arr[i], 1};
        } else {
            s.sum = sav[i-1][a].sum+arr[i];
            s.len = sav[i-1][a].len+1;
            if ((a == 0 && arr[i] < s.sum) || \
                (a == 1 && arr[i] > s.sum)) {
                s.sum = arr[i];
                s.len = 1;
            }

            int idxs = sav[i-1][a].idx;
            if ((a == 0 && s.sum < sav[idxs][a].sum) || \
                (a == 1 && s.sum > sav[idxs][a].sum))
                s.idx = i;
            else
                s.idx = idxs;
        }
    }
}

int main() {
    // initialize
    init(left, 0, 0);
    init(left, 1, 0);
    init(right, 0, 1);
    init(right, 1, 1);

    // compare
    int max, li, ri;
    bool flag;
    for (int i=1; i<sz; ++i) {
        const int &li_min = left[i-1][0].idx;
        const int &li_max = left[i-1][1].idx;
        const int &ri_min = right[i][0].idx;
        const int &ri_max = right[i][1].idx;
        int tmp1 = left[li_max][1].sum-right[ri_min][0].sum;
        int tmp2 = right[ri_max][1].sum-left[li_min][0].sum;
        if (i==1 || tmp1 > max) {
            max = tmp1;
            li = li_max;
            ri = ri_min;
            flag = 1;
        }
        if (tmp2 > max) {
            max = tmp2;
            li = li_min;
            ri = ri_max;
            flag = 0;
        }
    }

    // print
    cout<<max<<endl;
    for (int i=left[li][flag].len-1; i>=0; --i)
        cout<<' '<<arr[li-i];
    cout<<endl;
    for (int i=right[ri][!flag].len-1; i>=0; --i)
        cout<<' '<<arr[ri-i];
    cout<<endl;

    return 0;
}

 

源引自己的github.io

http://awarrior.github.io/maximal-difference/

 

posted @ 2015-03-30 13:42  awarrior  阅读(171)  评论(0编辑  收藏  举报