zoukankan      html  css  js  c++  java
  • 最大子列和

    //计算最大子列和,T(n)=O(n^2)
    #include <stdio.h>
    #include <stdlib.h>
    //一旦由i确定左端,thisSum就从左端往右加,加一个值更新一次thisSum
    //当第二个数作为左端时,thisSum要归0,因为这代表着第二种序列
    int main()
    {
        int a[n];
        int i,j;
        int maxSum=0,thisSum;
        for(i=0;i<n;i++)//i为左端
        {
            thisSum=0;
            for(j=i;j<n;j++)//j为右端
            {
                thisSum+=a[j];
                if(thisSum > maSum)
                    maxSum = thisSum;
            }
        }
        return 0;
    }
    View Code

    时间复杂度为O(N^2)

    第二种算法:分治法,复杂度为O(N*logN)

    分治的思想在于将数组分为左半部和右半部,且左右部相互独立,分别去求左半部和右半部的最大子列和

    再求从中轴线开始,向左扫描,得MaxLeftBorderSum和MaxRightBorderSum,将他们加起来得到贯穿中轴线的子列和

    最大子列和逃不出三个部分,所以max3(MaxLeftSum,MaxLeftBorderSum+MaxRightBorderSum)就是最大子列和

    //分治法计算最大子列和,时间复杂度为T(N*logN)
    #include <stdio.h>
    #include <stdlib.h>
    int A[N];
    int MaxSubSum(int A[],int left,int right)
    {
        int LeftSubSum,RightSubSum,LeftBorderSum=0,RightBorderSum=0;
        int center,MaxLeftBorderSum=0,MaxRightBordersum=0;
        if(left == right)
        {
            if(A[left] > 0)
                return A[left];
            else
                return 0;
        }
        center=(right+left)/2;
        LeftSubSum=MaxSubSum(A,left,center);
        RightSubSum=MaxSubSum(A,center+1,right);
        for(i=center; i >= left; i--)
        {
            LeftBorderSum+=A[i];
            if(LeftBorderSum > MaxleftBorderSum)
                MaxLeftBorderSum=LeftBorderSum;
        }
        for(i=center+1; i<=right; i++)
        {
            RightborderSum+=A[i];
            if(RightBorderSum > MaxRightBorderSum)
                MaxRightBorderSum= RightBorderSum;
        }
        return max3(LeftSubSum,RightSubSum,MaxLeftBorderSum+MaxrightBorderSum);
    }
    int main()
    {
        return MaxSubSum(A,0,N-1);
    }
    View Code

     求左半部的最大子列和,就和求一整块的最大子列和一样,再分成左半部和右半部

    每次递归,LeftBordersum/RightBordersum以及MaxBorderSum都从0开始

    疑惑的是如果都是负数,最大子列和不就为0吗?

    第三种算法:online algorithm(在线算法)

    每次加一个到ThisSum,如果某次小于0,ThisSum归0,因为让这个负的ThisSum再往后加,只可能让当前加的这个数变小

    所以,直接抛弃前面,从为正的开始

    这个算法的正确性让我难以证明

    //在线算法计算最大子列和,时间复杂度为T(N)
    #include <stdio.h>
    #include <stdlib.h>
    
    int SubSum(int A[])
    {
        int ThisSum=0,Maxsum=0;
        for(i=0;i<n; i++)
        {
            ThisSum+=A[i];
            if(ThisSum > MaxSum)
                MaxSum=ThisSum;
            if(ThisSum < 0)
                ThisSum=0;
        }
    }
    
    int main()
    {
        return SubSum();
    }
    View Code

    第二种算法的时间复杂度分析:

    T(n)=2T(n/2)+O(n)

    把O(n)换成n(目前的知识不知道为什么,结论是不影响)

    第一次:T(n)=2T(n/2)+n

    让T(n/2)递推:T(n/2)=2T(n/2^2)+n/2

    第二次:T(n)=2^2T(n/2^2)+2n

    ....

    ......

    第k次:T(n)=2^k*T(n/2^k)+k*n

    n/2^k最后会接近1,T(n/2^k)->T(1)=1

    且n=2^k -> k==log2 n

    -->T(n)=n+n*log n

    《算法及数据分析(c)》中默认了n为偶数,我的理解是这样才能使n*logn>n,否则就不能说复杂度是O(n*logn)(因为复杂度总是选取较大的项)

    且就算为奇数,分析要复杂些,解雇还是O(n*logn)...(这个地方的分析我先放放)

  • 相关阅读:
    深入理解java虚拟机(7)---线程安全 & 锁优化
    深入理解java虚拟机(6)---内存模型与线程 & Volatile
    java注解框架
    敏捷软件开发---闲话敏捷
    深入理解java虚拟机(5)---字节码执行引擎
    龙应台写给儿子安德烈的信
    wojilu中的路由
    如何使用豆约翰博客备份专家批量下载新浪微博
    haha
    http://www.jsbreakouts.org/---各种html5框架实现打砖块游戏 breakout
  • 原文地址:https://www.cnblogs.com/gabygoole/p/4597581.html
Copyright © 2011-2022 走看看