我试图在N大小的数组的k个元素中找到最小和次最小的元素(没有排序和最小/最大堆)。
使用传统的方法,首先从第< code>0个元素开始,在第< code>k个元素中找到最小的和第二小的元素,然后将起始点移动< code>1并重复该过程。但是它的复杂度是< code>O(Nk)。如果可能,我需要一个复杂度为< code>O(N)的解决方案。对此有什么建议吗?
在Jubobs的注释后编辑:例如,如果say数组是{12,1,78,90,57,89,56}
,而k
k是3k
elements
,最小的元素将是
k
elements
(1,78,90)
,最小的元素将是
78,依此类推。
以下是我用O(Nk)
复杂性编写的代码片段:
int j=0;
while(j < input.length-k+1) {
int i=j;
for(i=j; i < j+k; i++) {
if(input[i] < min) {
min2 = min;
min = input[i];
} else if(input[i] > min && input[i] < min2) {
min2 = input[i];
}
}
}
您可以使用一个保持排序的队列。
在每个步骤中,如果 deque 中的第一个元素(d.front.index
)相对于当前步骤早于 k
个步骤,请弹出它 (d.popFront()
)。
然后,当数组中当前位置的元素小于双端队列中的最后一个元素(d.back.value
)时,从双端队列中弹出元素(d.popBack()
)。
最后,将当前值添加到 deque 的末尾 (d.pushBack()
)。
在每个步骤中,d.front.值
将是 [步骤 - k 1,步骤]
的最小值。
您可以将 deque 存储为大小为 k
的链接列表。然后,您将始终可以访问其中的第二个元素,这将是[步骤 - k 1,步骤]
中的第二个最小元素。如果您最终由于弹出每个元素而只有一个元素,则必须小心。在这种情况下,弹出的那些可能是未来查询的第二小。您可以将这些保留在与 deque 类似的处理方式的另一个列表中,有关示例,请参阅下文。
这是 O(n)
摊销的,因为数组中的每个元素最多只能进入和离开 deque 一次。它可能看起来像O(nk),
因为你将有一些嵌套的循环,但是如果你考虑操作的总数,你会看到它实际上是O(n)
。
伪代码
for i = 0, i < n:
if not d.empty and i - d.front.index >= k:
d.popFront()
while not d.empty and d.back.value > a[i]:
d.popBack()
d.pushBack({index = i, value = a[i]})
output d.front.value as the minimum value in [i - k + 1, i]
用于跟踪第二个最小值的代码将保留为练习。
例如:
a = {12, 1, 78, 90, 57, 89, 56}, k = 3
d = {12}
d = {1} (12 popped, track this)
d = {1, 78} => we have to output smallest and second smallest in [0, 2].
=> smallest is always the first in the deque, so 1
=> second = min(12 [this was popped], 78) = 12
d = {1, 78, 90)
=> smallest 1, second is 78 (12 is too old now)
d = {57}
=> 1 popped for being too old, the others for being too large
=> smallest = 57, second = 78 (last popped)
d = {57, 89}
=> smallest = 57, second = 89
d = {56}
=> smallest = 56, second = 57
基本上,您为第二小的数组保留一个数组。这将包含尚未太旧的弹出值。这些也将按降序排序。
此方法的运行示例,其中d2
是第二个数组:
a = {12, 1, 78, 90, 57, 89, 56}
d = {12}, d2 = {}
d = {1}, d2 = {12}
d = {1, 78}, d2 = {12}
=> output 1, 12
d = {1, 78, 90}, d2 = {} - 12 was too old
=> output 1, 78
d = {57} d2 = {90, 78}
=> output 57, 78
d = {57, 89} d2 = {90} - 78 too old
=> output 57, 89 (if we had 91 instead of 89, we'd have output the 90 in d2)
d = {56} d2 = {89, 57}
=> output 56, 57
我有一个任务需要完成:
输入:p=1,r=55,x=5 产量:5 50 从1到55迭代后,如果数字之和=5,则可能的结果将5,14,23,32,41,50因此输出是一个越来越小的结果 我试着做下面的代码,但我正在从键错误中获取索引。我想这是因为此列表中没有添加任何内容。
我有一组向量,我需要用java编写算法,找到这个集合的最小元素。问题是,有些元素是无与伦比的。例如minset{(1,4,6),(3,2,5),(2,3,4),(5,4,6)} = {(1,4,6),(3,2,5),(2,3,4)}。对于最小元素集“minset”,以下内容成立:原始集的每个向量要么在“minset”中,要么在“minset”中
给定一个非负整数数组,设计最简单的算法来找到最大大小的子数组,并将其加到最小的值。 我的想法是,因为它们是非负整数,所以和最小的数组总是单个单元数组,只有原始数组的最小值。如果我理解正确的话,它取决于什么具有更高的优先级,具有更高的长度或更小的值。然而,这个问题从来没有明确说明哪一个优先。 我在这个问题上是正确的,还是我遗漏了什么?
给出了一系列成本。你可以向前跳两次,也可以向后跳一次。如果你在一个特定的指数上着陆,你必须把成本加到你的总数上。找到穿过数组或到达数组末端所需的最小成本。 输入: 输出: 说明:我们从指数1开始,跳到3然后跳出来,总成本为8 4=12。 我们如何为此构建DP解决方案?
考虑一个问题来寻找区间图的最小支配集。在区间调度的上下文中,它被转换为以下问题: 存在多个可能相互重叠的间隔。找到区间的最小子集,以便对于未包含在子集中的每个区间,它将在与它重叠的子集中找到至少1个区间。 有一个公认的贪婪解决方案可从互联网上的各种来源,例如康奈尔大学的一个解决方案:http://www.cs.cornell.edu/Courses/cs4820/2011sp/handouts/s