您的位置:首页 > Web前端

剑指offer:连续子数组的最大和

2016-03-10 21:07 393 查看
问题:求连续子数组的最大和

算法1:

首先用一个变量maxSum来保存最大和。

从数组的第一元素开始,遍历整个数组。并用currSum来保存遍历过程中最大子数组的和。

在遍历每个元素的时候:

1、首先,将这个元素和最大和maxSum比较,如果大于maxSum,就将这个元素赋给maxSum。

2、同时,判断当前子数组的和currSum是否大于0。如果currSum大于0,将这个元素的值和currSum相加。否则,将当前元素的值直接赋给currSum。(为什么?我是这么考虑的,如果遍历到第i个元素,第i个元素之前的子数组的和currSum,且currSum的值为负,那么如果currSum和第一个元素相加,不论第i个元素为什么,最终的和与第i个元素相比较,只会更小。所以说,如果currSum为负,currSum只会使削弱后面子数组的和,所以舍弃这个负的值)

3、比较currSum和maxSum,如果maxSum小于currSum,就把currSum赋值给maxSum

代码如下:

class Solution {

public:

//求解问题代码开始

    int FindGreatestSumOfSubArray(vector<int> array) {

        //

        if (array.size() == 0){

            //throw new exception();

            return 0;

        }

        

        int maxSum = 0x80000000;

        int currSum = 0x80000000;

        for (vector<int>::iterator ite = array.begin(); ite != array.end(); ite++){

            

            if (*ite > maxSum){

                maxSum = *ite;

            }

            if (currSum < 0){

                currSum = *ite;

            }

            else {

                currSum += *ite;

            }

            if (currSum > maxSum){

                maxSum = currSum;

            }

        }

    

        return maxSum;

    }
};

上面算法的优点是,多项式时间内即可完成比较。缺点是,没有给出哪段元素的和最大。

当然,也可采用分治算法求解这道题目。

算法2:采用分治法:

1、将一个数组分为两部分,左半部分和有半部分;分别求这两部分的最大子数组的和(递归)。

2、整个数组的最大子数组和也可能是跨越这两部分数组,因此还得求跨越左右两部分子数组的最大子数组和

3、最后比较这三部分,并返回最大值。

class Solution {

public:

    int FindGreatestSumOfSubArray(vector<int> array) {

        //

        if (array.size() == 0){

            //throw new exception();

            return 0;

        }

        

        int maxSum = 0x80000000;

        maxSum = FindGreatSumOfSubArray(array, 0, array.size() - 1);

    

        return maxSum;

    }

    int FindGreatSumOfSubArray(vector<int> &array, int begin, int end){

        if (begin == end){

            return array[begin];

        }

        int max = 0;

        int mid = (begin + end) / 2;.//使用mid将数组分为两部分

        int leftMax = FindGreatSumOfSubArray(array, begin, mid);//求左半部分最大和

        int rightMax = FindGreatSumOfSubArray(array, mid + 1, end);//求有半部分最大和

        //接下来求跨越左半部分和有半部分的最大和

        int midtoLeftMax = 0x80000000;

        int midtoRightMax = 0x80000000;

        int midMax;

        

        for (int i = mid, currSum = 0; i >= begin; i--){

            currSum += array[i];

            if (currSum > midtoLeftMax){

                midtoLeftMax = currSum;

            }

        }

        for (int i = mid + 1, currSum = 0; i <= end; i++){

            currSum += array[i];

            if (currSum > midtoRightMax){

                midtoRightMax = currSum;

            }

        }

        

        if (midtoLeftMax >= 0 && midtoRightMax >= 0){

            midMax = midtoLeftMax + midtoRightMax;

        }

        else {

            midMax = midtoLeftMax > midtoRightMax ? midtoLeftMax : midtoRightMax;

        }

        //返回左半部分最大和、有半部分最大和、跨越左半部分和右半部分最大和中最大的一个

        max = leftMax > rightMax ? leftMax : rightMax;

        max = max > midMax ? max : midMax;

        return max;

    }

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: