最大子数组(maximum subarray)问题

1. 分治策略:

数组a(长度为n)的最大子数组为:
1. a[0]到a[n/2]的最大子数组;
2. a[n/2+1]到a[n-1]的最大子数组;
3. a[i]到a[j],其中i <= n/2 <= j;

定义一个结构体承载返回结果:

typedef struct max_sub_array{
    int low;
    int high;
    int sum;

    max_sub_array(int l, int h, int s) {
        low  = l;
        high = h;
        sum  = s; 
    }
}max_sub_array;

包含中间值的最大子数组:

max_sub_array FindMaxCrossingSubArray(int* a, int low, int mid, int high) {
    int leftsum  = -MAXN;
    int rightsum = -MAXN;
    int sum      = 0;
    int max_left, max_right;
    max_left = max_right = mid;
    for (int i = mid; i >= low; i--) {
        sum = sum + a[i];
        if (sum > leftsum) {
            leftsum = sum;
            max_left = i;
        }
    }
    sum = 0;
    for (int i = mid + 1; i <= high; i++) {
        sum = sum + a[i];
        if (sum > rightsum) {
            rightsum = sum;
            max_right = i;
        }
    }

    max_sub_array ans(max_left, max_right, leftsum + rightsum);
    return ans;
}

最终的函数:

max_sub_array FindMaxSubArray(int* a, int low, int high) {
    if (high == low) {
        return max_sub_array(low, high, a[low]);
    } else {
        int mid = (low + high) / 2;
        max_sub_array left  = FindMaxSubArray(a, low, mid);
        max_sub_array right = FindMaxSubArray(a, mid + 1, high);
        max_sub_array cross = FindMaxCrossingSubArray(a, low, mid, high);

        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;
        }
    } 
}

2.线性时间解法:

其实我不觉得是线性时间,但是确实可以优化很多,思路就是当数组向后扩展的时候,我先假设我得到当前数组的最大子数组,然后判断如果新增加一个元素,是否能构成新的最大子数组。

max_sub_array LinearSolution(int* a, int low, int high) {
    if (high == low) {
        return max_sub_array(low, high, a[low]);
    } else {
        max_sub_array temp(low, low, a[0]);
        for (int i = low + 1; i <= high; i ++) { 
            if (a[i] > 0) {
                int max = a[i];
                int j   = i - 1;
                int low_ = temp.low;
                while(j >= low_) {
                    max = max + a[j];
                    if (max > temp.sum) {
                        temp.low = j;
                        temp.high = i;
                        temp.sum = max;
                    }
                    j--;
                }
            }
        }
        return temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值