maximum subarray

经典面试题

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(int A[], int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int max = A[0], max_neg = A[0], sum = 0;
        bool flag = false; // test if A[] contains all negtive integers
        for (int i = 0 ; i < n; i++)
        {
            if (A[i] >= 0)
                flag = true;
            else if (A[i] > max_neg)
                max_neg = A[i];

            sum += A[i];
            if (sum < 0)
                sum = 0;
            else if (sum > max)
                max = sum;
                
        }
        
        return flag?max:max_neg;
    }
};

主要思想是: 对于array[0...n],如果array[i...j]就是满足和最大的子串,那么对于任何k(i<=k<=j),我们有array[i...k]的和大于0。因为如果存在k使得array[i...k]的和小于0,那么我们就有array[k+1...j]的和大于array[i...j],这与我们假设的array[i...j]就是array中和最大子串矛盾。然后得考虑array全是负数的情况。


另附O(nlogn)解法:

分治法(divide and conquer)

注意到A[1...n]的最大子串A[i..j]可能来自于以下三种情况中的一种:

  • 1 ≤ i ≤ j ≤ n/2,也即最大子串出现在原串的左半部分
  • n/2 ≤ i ≤ j ≤ n,也即最大子串出现在原串的右半部分
  • 1 ≤ i ≤ n/2 ≤ j ≤ n,也即最大子串部分来自原串的最半部分,部分来自原串的右半部分

因此我们可以分别计算这三种情况下的解,然后将这三个解中最好的一个选出作为整个问题的解。

针对前两种情况,其实就相当于把问题的规模缩小了(divide)。把求长度为n的数组的最大子串变为求长度最n/2的数组的最大子串。这个规模变小了的问题的解同样可能有三种情况。对其中的前两种情况,我们依然采取细分的方法。可是,这样的细分会有头吗?当然会的,到了最后,我们会得到一个个长度为1的数组,在这种极限情况下,我们就不必考虑三种情况,因为此时的最大子串显然就是这个长度为1的子串自己(conquer)。

而针对第三种情况,我们采取另一种策略,即不是将问题化为相同的更小规模的问题,而是直接求解。我们首先求出A[i...n/2]使其为A[1...n/2]的最大子串,这里,进行一次遍历即可,时间复杂度为O(n)。同理,我们也可以求出A[n/2...j]使其为A[n/2...n]的最大子串。将这2个最大子串合在一起,就得到了所有会跨越串的中部的子串中的最大子串。

总结起来,假如使用T(n)代表使用此方法求解大小为n的数组的最大子串问题所消耗的时间,则有:

  • T(n) = 2T(n/2) + O(n),n>1
  • T(1) = O(1),n=1

不难发现,此时求解整个问题的时间复杂度为O(nlogn)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值