寻找最小的窗口

时间:2010-06-21 03:18:11

标签: c++ c algorithm

鉴于两个数组A[n]B[m],如何在A中找到包含B所有元素的最小窗口。

我试图在O(n)时间内解决这个问题,但我遇到了问题。是否有任何熟知的算法或程序来解决它。

2 个答案:

答案 0 :(得分:4)

如果m > nA无法包含B的所有元素(因此我们有O(1)解决方案)。

否则:

  • 创建一个哈希表,将B的元素映射到序列{0..m-1}(从O(n)起为m <= n)。
  • 创建一个数组C[m],以计算当前窗口中B(初始化为0)成员的出现次数。
  • 创建变量z以计算C的0个元素的数量(初始化为m)。

  • 创建变量se以表示当前窗口的开头和结尾

  • while e < n
    • 如果z非零,请增加e并更新CzO(1)
    • 否则将此窗口视为可能的解决方案(即,如果它是目前为止的最小值,则存储它),然后递增s并更新CzO(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;
    }
}

这种滑动有效,因为不同的“最小”窗口不能相互包含。