53. Maximum Subarray

来源:互联网 发布:ibm mq node 编辑:程序博客网 时间:2024/06/05 12:14

问题描述:

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

给一个数组,找到某个子数组使得子数组的元素相加的和最大

问题解决:

运用分治算法

将数组从中间项拆成前中后三部分

用递归求出前后两部分的最大子数组之和

再从中间的数开始,分别向前后扫描,每次跟一个元素相加,找到最大的相加后的和

分成三部分后,要么最后的结果不包含中间项,即前后两部分的最大子数组之和有一个是我们要的结果;

要么包含中间项,则通过向前向后求和取最大值

最后只要取前后两部分最大子数组之和、包含中间项的最大值中的最大值就是我们要的结果

代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //简单粗暴的方法O(n^2)
        /*int largest;
        int sum = 0;
        vector<int>::iterator iter1 = nums.begin();
        vector<int>::iterator iter2;
        largest = *iter1;
        for(; iter1 != nums.end(); iter1++) {
            sum = *iter1;
            if(sum > largest) {
                largest = sum;
            }
            for(iter2 = ++iter1; iter2 != nums.end(); iter2++) {
                sum += *iter2;
                if(sum > largest) {
                    largest = sum;
                }
            }
            iter1--;
        }
        return largest;*/
        //比较明智的方法O(n)
        /*int sum = 0;
        vector<int>::iterator iter1 = nums.begin();
        int result = *iter1;
        for(int i : nums) {
            sum = max(sum+i,i);
            result = max(sum,result);
        }
        return result;*/
        //分治算法O(nlogn)
        //若数组为空,返回0
        if(nums.empty()) return 0;
        //否则返回获取最大子数组之和的递归函数
        else return getMax(nums, 0, nums.size() - 1);
    }
    //分别传的是原数组,子数组的左右两个下标
    int getMax(vector<int>& nums, int left, int right) {
        //若左下标大于等于右下标,则返回左下标的值,即子数组长度为1时
        if(left >= right) return nums[left];
        
        //得到中间项下标
        int midn = left + (right - left)/2;
        
        //递归得到左右两部分的最大子数组之和
        int mleft = getMax(nums, left, midn-1);
        int mright = getMax(nums, midn+1, right);
        
        //定义包含中间项的最大子数组之和为中间项
        int mmid = nums[midn], t = mmid;
        
        //向前跟数组元素相加,保留最大的和
        for(int i = midn-1; i >= left; i--) {
            t += nums[i];
            mmid = max(mmid, t);
        }
        
        //定义t为向前加的最大和
        t = mmid;
        
        //向后跟数组元素相加,保留最大的和,则得到包含中间项的最大的和
        for(int i = midn+1; i <= right; i++) {
            t += nums[i];
            mmid = max(mmid, t);
        }
        
        //取三个部分的最大值
        return max(mmid, max(mleft, mright));
    }
};

原创粉丝点击