• 算法第二章上机实践报告


                               7-1 最大子列和问题                                                           

    给定K个整数组成的序列{ N1​​, N2​​, ..., NK​​ },“连续子列”被定义为{ Ni​​, Ni+1​​, ..., Nj​​ },其中 1。“最大子列和”则被定义为所有连续子列元素的和中最大者。

    例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

    问题应这样解释:从给定一个数组中 ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),然后返回其最大和(应该是要大于等于零)。

    int findmax(int *a,int left,int right)
    {
        if(left==right) return a[left];
        
        int mid=(left+right)/2;
        int lmax=findmax(a,left,mid);
        int rmax=findmax(a,mid+1,right);
        
        int add=0,addl=a[mid],addr=a[mid+1];
        
        for(int i=mid;i>=left;i--)
        {
            add+=a[i];
            if(add>addl) addl=add;
        }
        add=0;
        for(int i=mid+1;i<=right;i++)
        {
            add+=a[i];
            if(add>addr) addr=add;
        }
        
        return maxnum(addl+addr,addl,addr);
    }
    View Code

    函数 findmax 是核心递归代码,利用了递归分治的思想,每次递归进行三大步的操作,首先求出中点值,并从当前中心点向左搜索找出最大子序列和,然后从当前中心点向右搜索找出最大子序列和,最后以中心点下标分别向右和向左遍历找出最大子序列和,上述三者的最大值作为本层递归的返回值给上一层递归进行调用。实质上是从大(范围)到小(递归分解),再由小到大(返回求和)。

    每次将问题分解为两个子问题,每个子问题的长度为原问题的一半,递归本身的时间复杂度最坏情况下应为为O(log2 n),最后一次找到要找的数;

    对于n个元素的情况:

    第一次二分:n/2
    第二次二分:n/2^2= n/4
    ......
    m次二分:n/(2^m)
    在最坏情况下是在排除到只剩下最后一个值之后得到结果,所以为
    n/(2^m)=1;
    2^m=n;
     
    且每次递归中,有有限个O(1)操作,有两个循环体,一个是从头到中间,另外一个是从中间到尾部, 所以加起来时间复杂度就是 O(n)。
    所以时间复杂度为:O(n*logn);
     
    空间复杂度为O(1);

     心得:这道题比较经典,能使用分治法的题目也是万变不离其宗,先要思考好若是使用递归算法,返回什么值,分治操作范围是由大到小(求精确值),还是先由大到小再由小到大(求和),每次递归中有哪些步骤,这些步骤的先后顺序,以及递归调用的参数如何设置,考虑好这些,使用分治法处理一些比较简单的问题就能很快的梳理好算法思想。

     
     
  • 相关阅读:
    增加samba用户提示Failed to add entry for user
    二叉树
    excel技巧
    mongodb导入json文件
    mongodb导出数据csv格式
    mongoexport导出csv中文乱码
    左连接,结果大于左面的表验证 解释
    plsql 用法和技巧
    对javaNI和NIO理解
    TinyMCE4.x整合教程-Xproer.WordPaster
  • 原文地址:https://www.cnblogs.com/jospeer/p/13792805.html
Copyright © 2020-2023  润新知