当前位置: 首页 > 知识库问答 >
问题:

第二种算法是如何变得比第一种算法更有效的,第二种算法中子阵列的右侧是如何移动的?

赏逸春
2023-03-14

问题-给定一个n个数组,我们的任务是计算最大子数组和,即数组中连续值序列的最大可能和。当数组中可能有负值时,问题就很有趣了。数组={-1,2,4,-3,5,2,-5,2}。

第一种算法-

int best = 0;
    for (int a = 0; a < n; a++) {
        for (int b = a; b < n; b++) {
            int sum = 0;
            for (int k = a; k <= b; k++) {
                sum += array[k];
            }
        best = max(best,sum);
        }
    }
cout << best << "\n"; 

第二种算法-

int best = 0;
    for (int a = 0; a < n; a++) {
        int sum = 0;
        for (int b = a; b < n; b++) {
            sum += array[b];
            best = max(best,sum);
        }
    }
cout << best << "\n";

这是它在书中说的--从算法1中去掉一个循环,就很容易让算法1变得更高效。这可以通过在子数组右端移动时同时计算和来实现。

第二种算法中子数组的右端是如何移动的,有人能给我解释一下吗?

共有1个答案

齐泰
2023-03-14

第一个版本对从indexa到indexb的子数组的所有子数组和进行强力比较,我们将这些子数组称为sumssubsum(a,b)

第二个版本也是蛮力的,但使用了subsum(a,b+1)==subsum(a,b)+array[b+1]

换句话说:要知道第一个10元素的和,可以使用前面计算的第一个9元素的和。如果你想用笔和纸解决问题,这将是显而易见的,但第一个版本没有做到这一点。相反,第一个版本对于aB的所有组合都有两个嵌套循环,并且总是以新的sum=0开头,这是相当浪费的。

只考虑第一个版本的外部循环:

for (int a = 0; a < n; a++) {
    for (int b = a; b < n; b++) {
        int sum = 0;
        // ...
    }
}

这里//...计算子和(a,b)

在第二个版本中:

int best = 0;
for (int a = 0; a < n; a++) {
    int sum = 0;
    for (int b = a; b < n; b++) {
        sum += array[b];
        best = max(best,sum);
    }
}

外循环负责在不同的“左端”启动子数组。内圈“移动”了“端点”。最内部的循环体计算subsum(a,b)并且内部循环的下一次迭代使用上面的关系“移动”b到下一个索引来计算subsum(a,b)==subsum(a,b-1)+array[b]。因为A是固定在内循环中的,所以作者说的是“移动右端”。

 类似资料:
  • 我想计算一个二次型:in Julia 在这些情况下,最有效的计算方法是什么: 没有假设 是对称的 和是相同的() 和都是对称的 我知道朱莉娅有。但是我想知道它是否比BLAS呼叫更快。

  • 我们在前面的章节中看到,Java 提供了两种List接口的实现,ArrayList和LinkedList。对于一些应用,LinkedList更快;对于其他应用,ArrayList更快。 要确定对于特定的应用,哪一个更好,一种方法是尝试它们,并看看它们需要多长时间。这种称为“性能分析”的方法有一些问题: 在比较算法之前,你必须实现这两个算法。 结果可能取决于你使用什么样的计算机。一种算法可能在一台机

  • 在上一章,我们看到了神经网络如何使用梯度下降算法来学习他们自身的权重和偏差。但是,这里还留下了一个问题:我们并没有讨论如何计算代价函数的梯度。这是很大的缺失!在本章,我们会解释计算这些梯度的快速算法,也就是反向传播。 反向传播算法最初在 1970 年代被发现,但是这个算法的重要性直到 David Rumelhart、Geoffrey Hinton 和 Ronald Williams 的 1986年

  • 种子模块也叫核心模块,是框架中最先执行的部分。即便像jQuery那样的单文件函数库,它的内部也分很多模块,必然有一些模块执行时在最前面立即执行,有一些模块只有用到才执行。有的模块可有可无,存在感比较弱,只有在特定的浏览器下才运行。 种子模块就是其中的先锋,它里边的方法不一定要求个个功能齐全,设计优良,但一定要极具扩展性,常用,稳定。 扩展性是指通过他们能给将其它模块包含进来;常用是指绝大多数的模块

  • 本附录摘自 Allen B. Downey 的 Think Complexity 一书 , 也由 O’Reilly Media (2011)出版。 当你读完本书后,也许你可以接着读读那本书。 算法分析 (Analysis of algorithms) 是计算机科学的一个分支, 着重研究算法的性能, 特别是它们的运行时间和资源开销。见 http://en.wikipedia.org/wiki/Ana

  • 我试图访问使用一维数组映射定义的二维矩阵的值,并希望将该特定索引值存储在一个变量中。 该矩阵包含整数值,利用二维矩阵到一维数组映射的概念,得到“二元运算符操作数类型错误+第一类INT[]和第二类INT”的错误。 我试图访问矩阵fill中的诊断值,即fill[i-1][j-1],并希望将其存储在变量D seq_2中。length是矩阵中列的大小。 代码是