数据结构之一(引论及最大子序列和问题)

  • 时间复杂度:
  1. O记号:如果存在正常数cc0 使得当N>=n0T(N)<=cf(N),则记为 T(N) = O(f(N))

在大O记号中比较的其实是相对增长率,其实也就是求导后的比较。对于具体的数值是没有意义。比如:某个N0使得f(N0)<g(N0)是没有意义的。

T(N) = O(f(N))时,f(N)T(N)的一个上界

几个结论:

结论一:如果T1(N) = O(f(N))T2(N) = O(g(N)),那么

a) T1(N) + T2(N)  = O(f(N) + g(N)); 或者写成max( O(f(N)) , O(g(N)) ).

b) T1(N) * T2(N)  = O(f(N) * g(N));

结论二:对于任意常数klogkN = O(N),说明对数增长的很慢。

 

 

 

  •  问题一:最大子序列和问题:

问题描述:给定(包括负数)整数A1,A2,A3 ... AN, 求∑jk=iAk 的最大值。

例子:对于 -2 11 -4 13 -5 -2答案为20

 

解法1

直接枚举所有子序列:

public static int maxSubSum(int[] a){

int maxSum = 0;

for(int i = 0; i < a.length; i++){

    int thisSum = 0;

    for(int j = i; j < a.length; j++){

       thisSum += a[j];

       if(thisSum > maxSum){

           maxSum = thisSum;

}

}

}

return maxSum;

}

时间复杂度 O(N2)

 

解法二)

分治法:

像一般的分治法一样,分为Divide-conquer-combine几个阶段。

具体为

a)       以中点将序列分为两段 Divide

b)      递归求两段的最大子序列

c)      求以中点为轴向两边蔓延的最大子序列,并和b)求的两个值比较,return其中的最大值。

 

public static int maxSumRec(int[] a, int left, int rigth){

if(left == right){

    if(a[left] > 0)

        return a[left];

    else

        return 0;

}

int center = (left + right) / 2;    //divide

int maxLeftSum = maxSumRec(a, left, center);    //sub problem

int maxRightSum = maxSumRec(a, center + 1, right);  //sub problem

int maxLeftBorderSum = 0;

int leftBorderSum = 0;

for(int i = center; j >= left; i--){          //combine

    leftBorderSum += a[i];

    if(leftBorderSum > maxLeftBorderSum){

      maxLeftBorderSum = leftBorderSum;

}

}

int maxRightBorderSum = 0;

int rightBorderSum = 0;

for(int i = center + 1; i <= right; i++){    //combine

    rightBorderSum += a[i];

    if(rightBorderSum > maxRightBorderSum){

        maxRightBorderSum = rightBorderSum;

}

}

if(maxLeftSum < maxRightSum){

    maxLeftSum = maxRightSum;

}

if(maxLeftSum < maxLeftBorderSum + maxRightBorderSum){   //combine

    maxLeftSum = maxLeftBorderSum + maxRightBorderSum;

}

return maxLeftSum;

}

public static int maxSubSum(int[] a){

    return maxSumRec(a, 0, a.length - 1);

}

 

时间复杂度为Onlogn

 

解法三)

此题有一种线性时间的解法,而且只需要一次扫描即可得到答案,即所谓“联机算法”(on-line algorithm

public static int maxSubSum(int[] a){

int maxSum = 0 , thisSum = 0;

for(int j = 0; j < a.length; j++){

    thisSum += a[j];

    if(thisSum > maxSum)

        maxSum = thisSum;

    else if(thisSum < 0)

        thisSum = 0;   //这里还是很有技巧

}

return maxSum;

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值