Учитывая два массива A[n]
и B[m]
, как я могу найти самое маленькое окно в A
это содержит все элементы B
.
Я пытаюсь решить эту проблему в O (n) время, но у меня есть проблема при выполнении его. Есть ли, любой хорошо знает алгоритм или процедуру решения его.
countНазовем окно "минимальным", если его нельзя уменьшить. Т.е. после увеличения левой или уменьшения правой границы оно перестает быть действительным окном (не содержит всех элементов из B). В вашем примере их три: [0, 2], [2, 6], [6, 7]
Предположим, что вы уже нашли самое левое минимальное окно [left, right]. ([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;
}
}
Это скольжение работает, потому что разные "минимальные" окна не могут содержать друг друга.
Если m > n
, A
не может содержать все элементы B
(и, следовательно, у нас есть O(1)
решение).
Иначе:
B
на последовательность {0..m-1} (это O(n)
, так как m <= n
). C[m]
для подсчета случаев появления членов B
(инициализируйте в 0) в текущем окне. Создайте переменную z
для подсчета количества 0 элементов C
(инициализируйте в m
).
Создайте переменные s
и e
для обозначения начала и конца текущего окна
e < n
:
z
ненулевое, увеличиваем e
и обновляем C
и z
. O(1)
s
и обновляем C
и z
. O(1)
Можно показать, что цикл while имеет не более 2n
итераций. Так что все это O(n)
, я думаю.