C ++:查找子数组数组中的最大整数

时间:2016-02-15 04:47:03

标签: c++ arrays algorithm max sub-array

我面临一个问题,我想编写一个算法,可以返回更大数组中k个元素的每个连续子数组的max元素,并将这些最大元素读入自己的数组,如这样:

Given int array = {3, 7, 20, 6, 12, 2, 0, 99, 5, 16}, and int k = 4,
--> creates the array {20, 20, 20, 12, 99, 99, 99} 
[because there are 7 consecutive sub-arrays of size 4 within the given array:
{3, 7, 20, 6}, {7, 20, 6, 12}, {20, 6, 12, 2}, ... , {0, 99, 5, 16}
and the max element of these, respectively, is 20, 20, 20, ..., 99 which 
are read into the resulting array. 

现在这是我的问题:我知道如何在O(n ^ 2)复杂度中实现这一点,但是想让它更快,以便它可以是O(n),或者如果那样& #39;不可能,O(nlog(n))。有谁知道是否有更快的方法来做到这一点,如果有,怎么做?

1 个答案:

答案 0 :(得分:1)

首先,朴素算法的复杂性是 O(k(n-k + 1))(通常这近似为 O(kn)),而不是的为O(n ^ 2)即可。对于每个连续的子阵列( n-k + 1 可能),您必须执行 k 比较。

你可以使用一些 memoization 做更好的事情,使用另一个长度 k 的数组,我们可以调用maximums。该数组将存储下一个最大值的索引。

对于数据集的每次迭代,都会检查maximums的第一个元素。您删除任何"已过期"索引,现在第一个元素是你当前迭代的答案。

当您在数据中滑动窗口(大小 k )时,将当前索引推送到maximums,然后按如下所示进行修剪:索引{{1}处的值} 必须小于索引maximums[i]的值。如果不是,那么你继续将索引冒充到maximums[i-1]的开头,一次一个点,直到这成为真。

实际上,最好将maximums数组视为环形缓冲区。修剪过程将尾部缩回头部,同时弹出任何过期的#34;最大值(当窗口滑过它们时)会使头部前进一步。

它有点笨重,但这里有一些工作代码来说明:

maximums

现在,时间复杂度......

最好的情况是 O(n),如果您的所有数据都已排序(升序或降序),就会发生这种情况。

我认为,最糟糕的情况是 O(2n)。在一次迭代中需要 k 额外操作的唯一方法是,如果您已经具有线性复杂度的 k 步骤(以便环形缓冲区已满)。在这种情况下,环形缓冲区将为空以进行下一步。由于我们只能 n / k 次填充和清空环形缓冲区,因此偶然 k 操作会出现在 kn / k ,或者只是<强>名词

你应该能够证明,即使不断地部分清空环形缓冲区也会导致相同的复杂性。

最后,我们可以总结并调用整个事物 O(n),因为任何常数因素对于大 n 都无关紧要。它实际上比我预期的要好。 =)