Прямоугольная область в массиве
учитывая матрицу N*N, имеющую 1 в 0 и заданное целое число k, каков наилучший метод для поиска прямоугольной области, такой, что в ней есть k 1 ???
2 ответов
рассмотрим эту более простую проблему:
учитывая вектор размера N, содержащий только значения 1 и 0, найдите подпоследовательность, содержащую ровно k значений 1 в нем.
пусть A
заданный вектор и S[i] = A[1] + A[2] + A[3] + ... + A[i]
, что означает, сколько 1 в подпоследовательности A[1..i]
.
для каждого i
мы заинтересованы в существовании j <= i
такое, что S[i] - S[j-1] == k
.
нет O(n)
С a хэш-таблица, используя следующее соотношение:
S[i] - S[j-1] == k => S[j-1] = S[i] - k
let H = an empty hash table
for i = 1 to N do
if H.Contains (S[i] - k) then your sequence ends at i
else
H.Add(S[i])
теперь мы можем использовать это для решения данной проблемы в O(N^3)
: для каждой последовательности строк в данной матрице (есть O(N^2)
последовательности строк), рассмотрим эту последовательность для представления вектора и применим к ней предыдущий алгоритм. Вычисление S
немного сложнее в случае матрицы, но это не так сложно понять. Дайте мне знать, если вам нужно больше подробности.
обновление:
Вот как алгоритм будет работать на следующей матрице, предполагая k = 12
:
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
рассмотрим только первую строку:
0 1 1 1 1 0
считайте, что это вектор 0 1 1 1 1 0
и применяем алгоритм для более простой задачи на нем: мы обнаруживаем, что нет подпоследовательности, складывающейся до 12, поэтому мы двигаемся дальше.
рассмотрим первые две строки:
0 1 1 1 1 0
0 1 1 1 1 0
считать их вектором 0+0 1+1 1+1 1+1 1+1 0+0 = 0 2 2 2 2 0
и примените алгоритм для более простой задачи на нем: опять же, нет подпоследовательности, которая добавляет до 12, поэтому двигайтесь дальше.
рассмотрим первые три строки:
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
считайте их вектором 0 3 3 3 3 0
и применить алгоритм для более простой задачи на нем: мы находим последовательность, начинающуюся в позиции 2 и заканчивающуюся в позиции 5, чтобы быть решением. Из этого мы можем получить весь прямоугольник с помощью простой бухгалтерии.
Я могу сделать это с помощью O(N^3*log (N)), но уверен, что лучшее решение быстрее. Сначала вы создаете другую n * n матрицу B (начальная матрица-A). Логика B следующая:
B[i][j] - is the number of ones on rectangle in A with corners (0,0) and (i,j).
вы можете оценить B для O(n^2) динамическим программированием: B[i][j] = B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j].
теперь очень легко решить эту проблему с O (N^4), повторяя все правое дно (i=1..N, j=1..N, O (N^2)), слева внизу (z=1..j, O (N)), а справа-верхний (t=1..i, O (N)) и вы получаете количество единиц в этом прямоугольнике с помощью B:
sum_of_ones = B[i][j] - B[i][z-1] - B[t-1][j] + B[t-1][z-1].
Если вы получили точно k:k==sum_of_ones, то результат.
чтобы сделать это N^3*log (N), вы должны найти правый верхний двоичным поиском (так что не просто перебирать все возможные ячейки).