鉴于两个数组A[n]
和B[m]
,如何在A
中找到包含B
所有元素的最小窗口。
我试图在O(n)时间内解决这个问题,但我遇到了问题。是否有任何熟知的算法或程序来解决它。
答案 0 :(得分:4)
如果m > n
,A
无法包含B
的所有元素(因此我们有O(1)
解决方案)。
否则:
B
的元素映射到序列{0..m-1}(从O(n)
起为m <= n
)。C[m]
,以计算当前窗口中B
(初始化为0)成员的出现次数。创建变量z
以计算C
的0个元素的数量(初始化为m
)。
创建变量s
和e
以表示当前窗口的开头和结尾
e < n
:
z
非零,请增加e
并更新C
和z
。 O(1)
s
并更新C
和z
。 O(1)
可以显示while循环的迭代次数不超过2n
次。所以整个事情都是O(n)
,我想。
答案 1 :(得分:3)
countLet的调用窗口'minimal'如果无法减少的话。即,在增加其左边界或减少其右边界之后,它不再是有效窗口(不包含来自B的所有元素)。你的例子中有三个:[0,2],[2,6],[6,7]
让我们假设你已经找到最左边的最小窗口[左,右]。 ([0,2]在你的例子中)现在我们只是向右滑动。
// count[x] tells how many times number 'x'
// happens between 'left' and 'right' in 'A'
while (right < N - 1) {
// move right border by 1
++right;
if (A[right] is in B) {
++count[A[right]];
}
// check if we can move left border now
while (count[A[left]] > 1) {
--count[A[left]];
++left;
}
// check if current window is optimal
if (right - left + 1 < currentMin) {
currentMin = right - left + 1;
}
}
这种滑动有效,因为不同的“最小”窗口不能相互包含。