美文网首页
算法优化例子

算法优化例子

作者: crj1998 | 来源:发表于2019-02-25 12:48 被阅读0次

最大连续子序列和问题:给定(可能是负的)整数序列A_{1},A_{2}...A_{N},寻找(并标识)\sum_{k=i}^{j}A_{k}的值为最大的序列。如果所有的整数都是负的,那么最大连续子序列的和是0。

1、典型的O(N^3)算法

最简单的算法是直接的穷尽查找,即蛮力算法(Brute Force Algorithm),找出所有子序列并求和,遍历所有求和结果找出最大值。

int maxSubsequenceSum(int a[], int &start, int &end){
    int size = sizeof(a)/sizeof(a[0]);
    int maxSum = 0;
    // 起始位置遍历
    for (int i=0; i<size; i++){
        // 结束位置遍历
        for (int j=i; j<size; j++){
            int thisSum = 0;
            // 子序列求和
            for (int k=i; k<=j; k++){
                thisSum += a[k];
                if (thisSum>maxSum){
                    maxSum = thisSum;
                    start = i;
                    end = j;
                }
            }
        }
    }
    return maxSum;
}

这一算法非常简单易于理解,最外层循环需要执行n次,第二层循环需要执行n-i次,第三层循环执行j-i次,由此可得时间复杂度为\sum_{l=i}^{N} \sum_{j=i}^{N} \sum_{k=i}^{j}1 = N(N+1)(N+2)/6,即O(N^3)
在该算法中嵌套循环几乎贡献了所有的时间复杂度,简单的理解一个循环有N的时间复杂度,那么三层嵌套就是N的三次方。

2、改进的O(N^2)算法

由蛮力算法可知,导致时间复杂度的主要是循环,通过减少循环就可以降低时间复杂度。分析蛮力算法可得,第三层循环计算thisSum有太多的重复步骤,没必要每次都重新求和,利用\sum_{k=i}^{j}A_{k} = A_{j} + \sum_{k=i}^{j-1}A_{k}在第二层循环累加即可。

int maxSubsequenceSum(int a[], int &start, int &end){
    int size = sizeof(a)/sizeof(a[0]);
    int maxSum = 0;
    for (int i=0; i<size; i++){
        int thisSum = 0;
        for (int j=i; j<size; j++){
            thisSum += a[j];
            if (thisSum>maxSum){
                maxSum = thisSum;
                start = i;
                end = j;
            }
        }
    }
    return maxSum;
}

由于循环只有两层,所以时间复杂度降低为O(N^2)

3、线性算法
从平方算法降低到线性算法还需要再删除一个循环,但是平方算法降低到线性算法,不能只是简单的改变程序,需要思想。前两种算法本质上还是穷尽法,只不过有一些巧妙的改进,想要得到线性算法就需要改变思想。

可以通过分析来排除一些可能的子序列。如果一个子序列是负的,那么它绝对不会出现在最大连续子序列的开始部分,这非常容易理解,因为如果开始部分是负的,显然起到减小作用,为什么又要包含进去呢?以某一序列{a, b, c, d, e, f, g, h, i, j, k......y, z}为例,如果a是负的,肯定不会以a开头;如果cdef是负的,可以直接跳到g开始,可能会问为什么不从d开始呢?原因在于c肯定不会是负的,见a情况,那么整个是负的,c又是正的,那么def也肯定是负的,没有必要再考虑了。

int maxSubsequenceSum(int a[], int &start, int &end){
    int size = sizeof(a)/sizeof(a[0]);
    int maxSum = 0, thisSum = 0, start = 0;
    for (int i=0; i<size; i++){
        thisSum += a[i];
        // 如果和为负,起点设为下一位
        if (thisSum<0){
            thisSum = 0;
            start = i+1;
        }
        // 如果大于最大值,终点设为此位
        if (thisSum>maxSum){
            maxSum = thisSum;
            end = i;
        }
    }
    return maxSum;
}

由于只用到一个至多循环n次的循环,所以是一个线性算法。

总结

算法效率提升有两种,一是程序上的优化,一是设计思想上的优化。思想上的优化是本质上的改变。

相关文章

  • 算法优化例子

    最大连续子序列和问题:给定(可能是负的)整数序列,寻找(并标识)的值为最大的序列。如果所有的整数都是负的,那么最大...

  • 儿童学编程语言swift语言 ipad playgrounds4

    前面的例子我们已经学会了怎么规划路线,优化算法。这节课,我们来继续尝试找出最佳的算法。 在这个例子中,在前进的路线...

  • 优化方法总结

    优化算法框架 神经网络模型中有多种优化算法,优化算法的作用用来优化更新参数。对于优化算法而言,主要的框架如下。参数...

  • 梯度下降算法

    梯度下降是一种优化算法(无约束的非线性规划)。自己结合例子总结如下。 直接上例子: 函数:f(x) = x1-x2...

  • 粒子群python3实现

    粒子群优化算法(详细易懂_很多例子) 在实现的过程中由于对其算法理解不够遇到了一些小问题。于是又找到了上面这篇文章...

  • 优化器

    优化器(optim) 优化算法模块(torch.optim) torch.optim 实现了丰富的优化算法,包括S...

  • 8. 优化案例

    1. 十大经典算法及其优化2.几种常见的优化算法3. 经验之谈:优化算法两句话精炼总结

  • 冒泡算法

    一、常用冒泡算法 二、优化冒泡算法

  • sgd(params, lr, batch_size)

    定义优化算法

  • Task07

    一 优化算法进阶 一个常用优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有用解的问题做...

网友评论

      本文标题:算法优化例子

      本文链接:https://www.haomeiwen.com/subject/hzcmyqtx.html