Saturday, February 2, 2013

Divide and conquer Solution for Maximum Sub Array Problem

Here is C++ code for finding Maximum Sub-Array in a given array using Divide and conquer approach. The program follows the logic given in the book "Introduction to Algorithms".

So what is Maximum Sub Array?
Maximum sub-array is the sub array with largest sum.
For example for the sequence of values −2, 1, −3, 4, −1, 2, 1, −5, 4; the contiguous sub-array with the largest sum is 4, −1, 2, 1, with sum 6.

#include<iostream>
#include<vector>
#include<cstdlib>
#define MINUS_INFINITY -99999

using namespace std;

/*array of elements and its size*/
vector<int> a;
int size;

/*
 * function to find the max sub array in the mid
 */
void max_sub_array_in_mid(int l, int h, int *sum, int *low, int *high) {
    
    int current_sum;
    int l_sum = MINUS_INFINITY;
    int r_sum = MINUS_INFINITY;
    int mid = (l+h)/2;

    current_sum = 0;
    for(int i = mid; i >= l; i--) {
        current_sum += a[i];
        if(current_sum > l_sum)
        {
            l_sum = current_sum;
            *low = i;
        }
    }

    current_sum = 0;
    for(int i = mid+1; i <= h; i++) {
        current_sum += a[i];
        if(current_sum > r_sum) {
            r_sum = current_sum;
            *high = i;
        }
    }

    *sum = l_sum + r_sum;
}

/*
 * This function gets called recursively to find the max sub array 
 * which could be on left/right of mid or the one that is in between
 */
void max_sub_array(int l, int h, int *sum, int *l_index, int *r_index) {
    
    if(l==h) {
        *sum = a[l];
        *l_index = l;
        *r_index = l;
    }
    else {
        int mid = (l+h)/2;
        int l_low,l_high,l_sum;
        int r_low,r_high,r_sum;
        int mid_low,mid_high,mid_sum;

        max_sub_array(l, mid, &l_sum, &l_low, &l_high);
        max_sub_array(mid+1, h, &r_sum, &r_low, &r_high);
        max_sub_array_in_mid(l, h, &mid_sum, &mid_low, &mid_high);
        
        if(l_sum > r_sum && l_sum > mid_sum) {
            *sum = l_sum;
            *l_index = l_low;
            *r_index = l_high;
        }
        else if(r_sum > l_sum && r_sum > mid_sum) {
            *sum = r_sum;
            *l_index = r_low;
            *r_index = r_high;
        }
        else if(mid_sum > r_sum && mid_sum > l_sum) {
            *sum = mid_sum;
            *l_index = mid_low;
            *r_index = mid_high;
        }
    }
}

int main() {
    
    int sum = 0;
    int l_index = -1;
    int r_index = -1;

    cout<<"\nEnter array size\n";
    cin>>size;

    for(int i=0;i<size;i++) {
        //more weightage for negative numbers to generate good test cases
        a.push_back(rand()%100 - rand()%150);
    }
    
    cout<<"\n array is \n";
    for(int i=0;i < size;i++) {
        cout<<a[i]<<" ";
    }
    cout<<endl;

    //Algorithm begins here
    max_sub_array(0, size-1, &sum, &l_index, &r_index);

    cout<<"\n max sub array ranges from "<<l_index<<" to "<<r_index<<endl;
    cout<<"array is:\n";
    for(int i=l_index;i<=r_index;i++)
        cout<<a[i]<<" ";
    cout<<endl;

    return 0;
}

No comments: