求每个元素之和为最大的给定数组的子数组

来源:互联网 发布:软件开发w模型 编辑:程序博客网 时间:2024/05/08 17:41

给定的数组,元素可能为正或者为负

方法 1. broute-force

这个是最容易想到的方法,就是把每个可能的子数组列出来,计算出元素之和,然后把最大的挑出来。显然,这个算法的时间复杂度为 O(n^2)

struct tuple FindMaxSubArray(int *array, int size){    struct tuple t;    t.sum = INT_MIN;    int i, j;    for(i = 0; i < size; i++)    {           int sum = 0;        for( j = i; j < size; j++)        {            sum += array[j];            if(sum > t.sum)            {                t.sum = sum;                t.start = i;                t.end = j;            }        }    }           return t;}
struct tuple{    int start, end;    int sum;};


方法2: divide-and-conquer

把一个数组分成两个,使用递归的方法。时间复杂度是 O(nlgn)

struct tuple FindMaxCrossSubArray(int *array, int start, int mid, int end){    int i;    struct tuple left;    left.sum = INT_MIN;    int sum = 0;    for(i = mid; i >= start; i--)    {        sum += array[i];        if(sum > left.sum)        {            left.start = i;            left.end = mid;            left.sum = sum;        }    }    sum = 0;    struct tuple right;    right.sum = INT_MIN;    for(i = mid + 1; i <= end; i++)    {        sum += array[i];        if(sum > right.sum)        {            right.start = mid + 1;            right.end = i;            right.sum = sum;        }    }    struct tuple combined = {left.start, right.end, left.sum + right.sum};    return combined;}

struct tuple FindMaxSubArray2(int *array, int start, int end){    struct tuple t;    if(start == end)    {        t.start = start;        t.end = end;        t.sum = array[start];        return t;    }    else    {        int mid = (start + end) / 2;        struct tuple left, right, cross;        left = FindMaxSubArray2(array, start, mid);        right = FindMaxSubArray2(array, mid + 1, end);        cross = FindMaxCrossSubArray(array, start, mid, end);        if(left.sum >= right.sum && left.sum >= cross.sum)        {            return left;        }        else if(right.sum >= left.sum && right.sum >= cross.sum)        {            return right;        }        else        {            return cross;        }    }}

3. 通过分析数组 array[i]的最大子数组来确定 array[i+1]的最大子数组。这种方法的时间复杂度可以降低到 O(n).

struct tuple find_maximum_subarray4(int *array, unsigned left, unsigned right) {    struct tuple suffixes[right - left + 1];     int i;    suffixes[0].start = left;    suffixes[0].end = left;    suffixes[0].sum = array[left];    for (i = left + 1; i <= right; i++) {        if (suffixes[i - 1].sum < 0) {            suffixes[i].start = i;            suffixes[i].end = i;            suffixes[i].sum = array[i];        } else {            struct tuple  *previous = &suffixes[i - 1];             suffixes[i].start = previous->start;            suffixes[i].end = i;            suffixes[i].sum = previous->sum + array[i];        }    }       struct tuple *max = &suffixes[0];    for (i = left + 1; i <= right; i++) {        if (max->sum < suffixes[i].sum) {            max = &suffixes[i];        }    }       return *max;}

对一个大小为10万的随机数组进行测试,

三种算法花费的时间分别为:

ime spent: 14.598223 secondstime spent: 0.007730 secondstime spent: 0.001730 seconds


0 0