zoukankan      html  css  js  c++  java
  • 最大字段和各种不同算法实现(参考编程珠玑)

    求最大字段和的算法很好的讲解了算法设计技术。根据《编程珠玑》上的描述,简单实现各种不同的算法。如下:

    1、最简单的方法:对所有满足0≤i≤j<n的(i,j)整数进行迭代。对每个整数对,都计算x[i..j]的总和:

    简单方法
    int maxSum_easy(int n, int* a, int& besti, int& bestj) //最简单的方法,复杂度为O(n^3)
    {
        int maxSoFar = 0, i = 0, j = 0, k = 0, sum = 0;
        for (i = 0; i < n; ++i)
            for ( j = i; j < n; ++j)
            {
                sum = 0;
                for (k = i; k<=j; ++k)
                    sum += *(a+k);
                if (sum > maxSoFar)
                {
                    maxSoFar = sum;
                    besti = i;
                    bestj = j;
                }
                
            }
        return maxSoFar;
    }

    2、改进简单的方法,将复杂度变为O(n2),注意子和求解过程,分别有两种改进方法:

      方法一,如下: 

    改进一
    int maxSum_O2na(int n, int *a, int& besti, int& bestj)//改进上一算法,时间复杂度变为O(n^2)
    {
        int maxSoFar = 0, i = 0, j = 0, k = 0, sum = 0;
        for (i = 0; i < n; ++i)
        {
            sum = 0;
            for (j = i; j < n; ++j)
            {
                sum += *(a+j);
                if (sum > maxSoFar)
                {
                    maxSoFar = sum;
                    besti = i;
                    bestj = j;
                }
            }
        }
        return maxSoFar;
    }

      方法二,如下:

    改进二
    int maxSum_O2nb(int n, int *a, int& besti, int& bestj) //增加一累加数组,时间复杂度变为O(n^2)
    {
        int maxSoFar = 0, i = 0, j = 0,  sum = 0;
        int * acc = new int[n+1]; //创建一个额外的累加器
        *(acc) = 0;
        for (i = 1; i <= n; ++i)
            *(acc+i) = * (acc+i-1) + *(a+i-1);
        for (i = 0; i < n; ++i)
            for (j = i; j < n; ++j)
            {
                sum = *(acc+j+1) - *(acc+i); // sum is sum of a[i..j]
                if (sum > maxSoFar)
                {
                    maxSoFar = sum;
                    besti = i;
                    bestj = j;
                }
            }
        delete acc;
        return maxSoFar;
    }

    3、同时,还可以利用分治法对其进行求解,复杂度为O(nlogn)代码如下:

    分治法求解
    int maxSum_ConDiv(int *a, int left, int right)//分治法,复杂度为O(nlogn),调用形式为maxSum_ConDiv(a,0,n-1)
    {
        int maxSoFar = 0, sum = 0, i = 0, m = (left+right)/2, lmax =0, rmax = 0, lsub = 0, rsub =0;
        if (left > right) //zero elements
            return 0;
        if (left == right) //one element
            return left > 0 ? left : 0;
        for (i = m; i >= left; --i)
        {
            sum += *(a+i);
            if (sum > lmax)
                lmax = sum;
        }
        sum = 0;
        for (i = m+1; i <= right; ++i)
        {
            sum += *(a+i);
            if (sum > rmax)
                rmax = sum;
        }
        
        //find max value among the 3 values and return it
        lsub = maxSum_ConDiv(a,left,m);
        rsub = maxSum_ConDiv(a,m+1,right);
        maxSoFar = lmax + rmax;
        if (lsub > maxSoFar)
            maxSoFar = lsub;
        if (rsub > maxSoFar)
            maxSoFar = rsub;
        return maxSoFar;
    }

    4、另外一种方法,是效率最高的,复杂度为O(n),利用了动态规划的思想,代码如下:

    动态规划求解
    int maxSum_sm(int* a, int n) //扫描算法,时间复杂度为O(n)
    {
        int maxSoFar = 0, maxendinghere = 0, i =0, temp =0;
        for (; i < n; ++i)
        {
            maxendinghere = maxendinghere+a[i];
            maxendinghere = maxendinghere > 0 ? maxendinghere : 0;
            
            if (maxendinghere > maxSoFar)
                maxSoFar = maxendinghere;
        }
        return maxSoFar;
    }

    测试实验如下所示:

    int main()
    {
        int a[] = {31, -41, 59, 26, -53, 58, 97, -93, -23, 84},
            n, besti = 0, bestj = 0, maxSum = 0;
        n = sizeof(a)/sizeof(a[0]);
        cout << "a的最大子和为:" <<  maxSum_sm(a,n) << endl;
        //cout << ";是 " << besti << "->" << bestj << "的和" << endl;
        return 0;
    }
  • 相关阅读:
    HTML中CSS入门基础
    HTML基本代码教学,第三天
    HTML基本代码教学,第二天
    HTML基本代码教学片,认识HTML
    开学第一天,规章制度,教学大纲
    新的学期,从头开始
    开启新模式WinForm
    封装、继承、多态的基本详细使用方式与方法以及含义
    Python开发基础-Day4-布尔运算、集合
    Python开发基础-Day3-列表、元组和字典
  • 原文地址:https://www.cnblogs.com/lyfruit/p/3021317.html
Copyright © 2011-2022 走看看