最大子数组求解问题(算法导论)

最大子数组问题求解

问题描述

一个数组中包含的元素有正有负,在该数组中寻找出一个连续非空子数组,要求该连续子数组的和最大,这就是最大子数组问题。
比如 nums = [4,3,-1,2,-2,-3,1],那么最大子数组就是[4,3,-1,2],和为4+3-1+2 = 8.

思路

利用分治法求解最大子数组问题。假定我们需要寻找数组nums[low,high]的最大子数组,使用分治法意味着我们要将子数组划分为两个规模尽量相等的子数组,也就是说,找到数组中央的位置,比如mid,然后考虑求解nums[low,mid]和nums[mid+1,high],nums的子数组只有如下三种情况:
1.完全位于子数组A[low,mid]中;
2.完全位于A[mid+1,high]中;
3.跨越了中点。

C++代码如下

#include <iostream>
using   namespace   std;
struct sumBorder{
    int left;
    int right;
    int summax;
};
sumBorder get_maxSubarraycrossmid(int *nums, int low, int high, int mid);
sumBorder get_maxsumary(int *nums, int low, int high);
int main()
{

    int *nums = new int[8];
    sumBorder rst;
    for (int i = 0; i < 8; i++){
        *(nums + i) = i - 5;
        cout << *(nums + i) << endl;
    }
    cout << "我是分隔符O(∩_∩)O~"<<endl;
    rst = get_maxsumary(nums, 0, 7);
    cout << rst.left << endl;
    cout << rst.right << endl;
    cout << rst.summax << endl;
    system("pause");
    return 0;

}
sumBorder get_maxSubarraycrossmid(int *nums, int low, int high, int mid)
{
    int max_sumleft = 0;
    int sum_left = 0;
    int left_order = 0;
    sumBorder ret;
    for (int i = mid; i >=low; i--)
    {
        sum_left += nums[i];
        if (sum_left > max_sumleft)
        {
            max_sumleft = sum_left;
            left_order = i;
        }
    }
    int max_sumright = 0;
    int sum_right = 0;
    int right_order = 0;
    for (int i = mid + 1; i <= high; i++)
    {
        sum_right += nums[i];
        if (sum_right > max_sumright)
        {
            max_sumright = sum_right;
            right_order = i;
        }
    }
    ret.left = left_order;
    ret.right = right_order;
    ret.summax = max_sumleft + max_sumright;
    return ret;
}
sumBorder get_maxsumary(int *nums, int low, int high)
{
    /*int *p1 = new int[8];*/
    sumBorder rut,rut_left,rut_right,rut_cross;

    if (low == high)
    {
        rut.left = low;
        rut.right = high;
        rut.summax = nums[low];
        return rut;
    }
    else{
        int mid = (low + high) / 2;

        rut_left = get_maxsumary(nums, low, mid);
        rut_right = get_maxsumary(nums, mid + 1, high);
        rut_cross = get_maxSubarraycrossmid(nums, low, high, mid);
    }
    if ((rut_left.summax >= rut_right.summax)&&(rut_left.summax>=rut_cross.summax)){

        return rut_left;
    }

    else if ((rut_right.summax >= rut_left.summax) && (rut_right.summax >= rut_cross.summax)){
        return rut_right;
    }   
    else
    {   
        return rut_cross;
    }
}

总结

楼主属于算法小白,最近才开始把一些经典的算法由“懂的”转化为可以写出来,代码都是亲测通过的,希望大神指出楼主考虑不全的地方。
C++返回多个值用结构体很方便,前一段写一个网络帧分析的软件,返回指针总是出现莫名其妙的值,改成结构体稳定多了,还是指针没学明白啊。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值