您将获得一个整数流,并且窗口大小为整数k,您将只逐个接收流整数。无论何时收到整数,都必须返回包含当前条目的最后k个整数中的最大数。
Interviewer期待O(N)Time + O(1)平均空间复杂度解决方案用于N个任务,并且数组中没有给出整数,每次只有一个整数将作为输入传递给您的方法。
我试过解决它,但无法提出O(N)解决方案。谁能告诉我我们怎么做呢。
答案 0 :(得分:2)
假设k
很小且不属于缩放参数 N (问题是 N 是任务的数量,但这并不十分清楚这意味着什么。)
max
变量max
,if is(不可能是max
的所有值),然后运行FIFO的k
个元素并重新计算{ {1}},否则不要。摊销,这是 O(1)。max
进行比较,并在必要时更新max
。max
推入FIFO。然后时间是 O(1),内存是 O(k + 1)。我不知道你至少没有存储要求 O(k)。处理 N 整数的时间是 O(N)。
答案 1 :(得分:1)
O(N)时间很容易,但O(1)平均空间是不可能的。
这是我们绝对需要存储的内容。对于我们在最后k个输入中看到的任何数字x
,如果我们看到x
后的数字更大,我们可以忘记x
,因为我们&# 39;永远不需要将它返回或再次与任何东西进行比较。如果我们自x
以来没有看到更大的数字,我们需要存储x
,因为我们可能必须在某个时候返回它。因此,我们需要在最后的k个项目中存储最大的数字,之后是最大的数字,以及之后的最大数字,一直到当前输入。在最坏的情况下,输入是下降的,我们总是需要存储所有最后的k个输入。在一般情况下,我们需要随时跟踪O(log(k))项;但是,峰值内存使用量将大于此值。
我们使用的算法是简单地跟踪我们刚才所说的我们需要存储的所有数字的双端队列,以它们的自然降序排列,以及我们看到它们时*。当我们收到一个输入时,我们会从双端队列的右侧弹出低于它的所有内容,然后按下双端队列右侧的输入。我们向左看,如果我们看到左边的项目比窗口大小旧,我们弹出左边。最后,我们向左看,我们看到的数字是最大滑动窗口。
此算法以分摊的常量时间处理每个输入。处理不是恒定时间的输入的唯一部分是我们可能弹出所有deque的部分,但由于每个输入仅在算法的过程中弹出一次,所以仍然是摊销不变。因此,该算法需要O(N)时间来处理所有输入。
*如果N非常大,我们可以跟踪我们看到事物mod k的指数,以避免溢出问题。
答案 2 :(得分:0)
首先,大多数采访者会将记忆O(k)视为O(1)。
鉴于细节很少,你可以实现一个环形缓冲区:
int numbers[k]; // O(1) because k is constant
int i = 0, next_number;
while (next_number= new_number()) {
numbers[i % k]= next_number;
i++;
if (i >= k) {
int max= MIN_INT;
for (int j= 0; j < k; j++) { // O(1) because k is constant
if (numbers[j] > max) max = numbers[j];
}
yield(max);
}
}
当然,如果他们不认为O(k)是O(1),那么问题就无法解决,他们要么搞砸了他们的问题,要么就是希望你说问题是错。
这里的fifo / deque通常更快(k高于某个数字),我只是展示了一个愚蠢问题的最简单答案。
答案 3 :(得分:-2)
这是我想到的答案(C ++)
#include <iostream>
#include <limits>
using namespace std;
int main()
{
cout << "Enter K: " << endl;
int K;
cin >> K;
cout << "Enter stream." << endl;
int n, counter = 1, max = std::numeric_limits<int>::min();
while (cin >> n){
if (counter % K == 0)
max = std::numeric_limits<int>::min();
if (n > max)
max = n;
cout << max << endl;
++counter;
}
}