我正在研究用于获取数组中子数组的最大总和的算法,并且我无法理解代码背后的逻辑。具体来说,这一行import
。我不明白这里做了什么。此外,此算法的复杂性是max_ending = max(0, max_ending + number)
还是O(n)
?:
O(n^2)
谢谢
答案 0 :(得分:1)
这取自算法手册简介的练习4.1-5。 由于这个问题及其答案解决了这个问题。我认为这可能会有所帮助。
“使用以下想法为最大子阵列问题开发非递归的线性时间算法。从数组的左端开始,向右前进,跟踪到目前为止看到的最大子数组。 A [1 .. j]的最大子阵列,通过使用以下观察,扩展答案以找到在索引j + 1处结束的最大子阵列:A [1 .. j + 1]的最大子阵列是最大子阵列A [1 .. j]或子阵列A [i .. j +1],对于某些1< = i< = j + 1。确定形式A [i ... j + 1]的最大子阵列在基于知道在索引j处结束的最大子阵列的恒定时间内。“
<强>答案强> 首先,我们需要找出在索引j + 1结束的最大子数组,它可能只是A [j + 1]或者以j加A [j + 1]结束的最大子数组,因此我们找到这两个的最大值。
一旦我们将最大子数组结束于索引j + 1,我们再次找到A [1..j + 1]的最大值,得到在索引j + 1结束的最大子数组和最大子数组之间的最大值A [1..j]。
所以基本上这个想法是让最大子数组在每次迭代的当前索引处结束,并获得上一次迭代的最大值和最大值之间的最大值。
我认为这是不正确的
编辑:如果数组不需要包含至少一个正数,这将取决于定义。否则你的没事。
max_ending = max(0, max_ending + number);
它应该是:
max_ending = max(number, max_ending + number);
如果你跟随mi变化,max_ending和max_so_far也应该从数字[0]和索引1的循环开始。
该算法的复杂性为O(n)
附加说明: 在您的版本中,无需获取number和max_ending +数字之间的最大值,因为max_ending&gt; = 0所以数字&lt; = number + max_ending
答案 1 :(得分:1)
你提出的算法似乎是杰伊卡丹的归因(Wikipedia)。这一行max_ending = max(0, max_ending + number)
意味着我们只关注非负数;换句话说,如果向当前子阵列添加一个元素将导致负和,则在该索引处使最大和结束为零(即,子阵列再次为空)。这条线依赖于我们需要重置被检查的子阵列窗口的唯一时间是它是否下降到零以下 - 即使稍后可以添加大的正元素,也可以获得更大的子阵列总和而不会在中间下降到负值。让我们看一个例子(max_ending
表示以当前索引结尾的子数组的最大总和):
{1,2,23,-4,3,-10}
max_ending 1 3 26 22 25 15
max_so_far 1 3 26 26 26 26
此算法的时间复杂度评估为O(n)
,因为每个数组元素需要访问一次,迭代次数以线性方式依赖于数组大小。 O(n^2)
意味着对于每个数组元素,迭代次数将是数组大小的顺序;因此,当数组大小增加时,迭代次数将以二次方式增加。
答案 2 :(得分:0)
https://app.codility.com/programmers/lessons/9-maximum_slice_problem/max_slice_sum/
编码测试将有助于更多地了解为max_ending选择0或其他值。正如@גלעדברקן所说,到目前为止,是否要丢弃切片是重要的决定点。
答案 3 :(得分:-1)
假设sum[i]
是序列结尾与numbers[i]
的总和,然后是sum[i] = max(numbers[i], numbers[i] + sum[i-1])
,答案是max(sum[i] for i from 0 to numbers.size() - 1)