zoukankan      html  css  js  c++  java
  • 《算法导论》——MaximumSubArray

      今天我们讨论的算法是最大子数组问题。

      首先我定义了一个类用来保存最大子数组的开始位置索引、结束位置索引和该数组的和。代码如下:

    class MaximumSubArray
        {
        private:
            int begin;    //开始位置索引
            int end;    //结束位置索引
            int sum;    //
        public:
            void setBegin(int Begin)
            {
                begin=Begin;
            }
            void setEnd(int End)
            {
                end=End;
            }
            void setSum(int Sum)
            {
                sum=Sum;
            }
    
            int getBegin()
            {
                return begin;
            }
            int getEnd()
            {
                return end;
            }
            int getSum()
            {
                return sum;
            }
        };
    View Code

      该算法采用分治策略,我们先讨论最大子数组跨越中点位置的情况:

    MaximumSubArray FindMaxCrossingSubArray(int *numArray,int low,int middle,int high)
        {
            MaximumSubArray max;
            int leftsum=numArray[middle];        
            int maxleft=middle;
            int sum=0;
            for(int i=middle;i>=low;i--)
            {
                sum+=numArray[i];
                if(sum>=leftsum)
                {
                    leftsum=sum;
                    maxleft=i;
                }
            }
            int rightsum=numArray[middle+1];
            int maxright=middle+1;
            sum=0;
            for(int j=middle+1;j<=high;j++)
            {
                sum+=numArray[j];
                if(sum>=rightsum)
                {
                    rightsum=sum;
                    maxright=j;
                }
            }
            max.setBegin(maxleft);
            max.setEnd(maxright);
            max.setSum(leftsum+rightsum);
            return max;
        }
    View Code

      接下来是二分法求最大子数组:

    MaximumSubArray FindMaximumSubArray(int *numArray,const int low,const int high)
        {
            MaximumSubArray max;
            if(high==low)
            {
                max.setBegin(low);
                max.setEnd(high);
                max.setSum(numArray[low]);
                return max;
            }
            if(high-1==low)
            {
                max.setBegin(high);
                max.setEnd(high);
                max.setSum(numArray[high]);
                return max;
            }
            int middle=(low+high)/2;
            MaximumSubArray left=FindMaximumSubArray(numArray,low,middle);
            MaximumSubArray right=FindMaximumSubArray(numArray,middle,high);
            MaximumSubArray cross=FindMaxCrossingSubArray(numArray,low,middle,high);
            if(left.getSum()>=right.getSum()&&left.getSum()>=cross.getSum())
                max=left;
            else if(right.getSum()>left.getSum()&&right.getSum()>=cross.getSum())
                max=right;
            else
                max=cross;
            return max;
        }
    View Code

    注意:

      该书中的伪代码并没有以下这段

    if(high-1==low)
            {
                max.setBegin(high);
                max.setEnd(high);
                max.setSum(numArray[high]);
                return max;
            }

    因为在算法递归到数组中只有两个元素的时候,算出的middle值和low值是一样的(& 索引为0和1的两个元素),所以,在high==low的时候去索引小的元素,在high-1=low的时候取索引大的元素,避免无限循环。

    以上代码,请放到如下注释的位置,保存为SubArray.h

    #include <stdlib.h>
    
    namespace dksl
    {
    //
    //
    //
    }

      下面是程序测试代码及运行结果:

    #include "stdafx.h"
    #include <iostream>
    #include "SubArray.h"
    
    using namespace std;
    using namespace dksl;
    int _tmain(int argc, _TCHAR* argv[])
    {
        int a[16] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};   
        MaximumSubArray max=FindMaximumSubArray(a,0,15);
        cout<<"begin:"<<max.getBegin()<<endl;
        cout<<"end:"<<max.getEnd()<<endl;
        cout<<"sum:"<<max.getSum()<<endl;
        system("PAUSE");
        return 0;
    }
    View Code

    该算法的时间复杂度为θ(nlogn)

  • 相关阅读:
    【存储过程】输入学生的姓名,打印出学生的最高分、最低分、平均分
    Oracle序列Sequence用法
    Oracle数据库正则表达式
    Oracle数据库添加约束
    CVX使用手册翻译
    波束赋形技术
    IRS与物理层安全
    5G关键技术总结
    2019年研究生数学建模竞赛
    2019年华为软挑总结
  • 原文地址:https://www.cnblogs.com/DKSL/p/3147448.html
Copyright © 2011-2022 走看看