时间复杂度分析实例(一)

题目描述

最大子列和问题:
给定N个整数的序列{ A 1 A_{1} A1 A 2 A_{2} A2,···, A N A_{N} AN},求函数 f ( i , j ) = m a x ( 0 , f(i,j) = max(0 , f(i,j)=max(0 ∑ k = i j A k \sum_{k = i}^{j}A_{k} k=ijAk ) ) )的最大值;

解决方法

解法一

// 解法一:
int MaxSum1(int A[],int N)
{
    int ThisSum,MaxSum = 0;
    int i,j,k;
    for(i = 0;i < N; i++)           //i为子列左端位置
    {
        for(j = i;j < N; j++)       //j为子列右端位置
        {
            ThisSum = 0;            //ThisSum为从A[i]到A[j]的子列和
            for(k = i;k <= j; k++)
                ThisSum += A[k];
            if(ThisSum > MaxSum)    //若新的子列和更大,则更新结果
                MaxSum = ThisSum;
        }
    }
    return MaxSum;
}

函数中有三重循环,通过分析证明可知,时间复杂度为 O ( N 3 ) O(N^{3}) ON3;

解法二

// 解法二
int MaxSum2(int A[],int N)
{
    int ThisSum,MaxSum = 0;
    int i,j,k;
    for(i = 0;i < N; i++)           //i为子列左端位置
    {
        ThisSum = 0;                //ThisSum为从A[i]到A[j]的子列和
        for(j = i;j < N; j++)       //j为子列右端位置
        {
            ThisSum += A[j];        //对于相同的i,不同的j,只要在j-1次循环基础上累加一项即可
            if(ThisSum > MaxSum)    //若新的子列和更大,则更新结果
                MaxSum = ThisSum;
        }
    }
    return MaxSum;
}

显然,解法二的时间复杂度要比解法一小得多,对于相同的i,不同的j,只需在j-1次循环的基础上累加一项即可,因此只有两重循环,分析可得,时间复杂度为 O ( N 2 ) O(N^{2}) ON2

解法三

// 解法三
int MaxSum3(int A[],int N)
{
    int ThisSum,MaxSum;
    int i;
    ThisSum = MaxSum = 0;
    for(i = 0;i < N; i++)
    {
        ThisSum += A[i];         //向右累加
        if(ThisSum > MaxSum)
            MaxSum = ThisSum;    //发现更大的子列和则更新当前结果
        else if(ThisSum < 0)     //如果当前子列和为负
            ThisSum = 0;         //则不可能使后面的部分和增大,抛弃之
    }
    return MaxSum;
}

解法三的时间复杂度明显要远远小于解法一和解法二,分析可知,解法三的时间复杂度为 O ( N ) O(N) ON
分析(在线处理算法):
解法三从0开始向右累加,如果子列和大于已知最大子列和,则更新最大值,继续累加,每累加一次进行判断,如果当前子列和为负数,则舍弃当前子列,ThisSum置零,从下一个元素开始继续累加,因为当子列和为负数时,继续累加只会使后面的和变得更小;

解法四

除了以上三种解法外,还有一种“分而治之”的解法,将数组分为左右两部分,分别求最大值,再求通过分割线的子列最大值,三者比较取最大值,其时间复杂度介于解法二和解法三之间,为 O ( N log ⁡ N ) O(N\log N) ONlogN;

【注】以上题目及解法摘自浙大数据结构慕课

你可能感兴趣的:(时间复杂度分析实例(一))