Алгоритм Сравнения матриц

Если у Вас есть 2 Матрицы размеров N*M. что лучший способ состоит в том, чтобы получить различие Rect?

Пример:

2 3 2 3 2 3 2 3                      2 3 2 3 2 3 2 3
2 3 2 3 2 3 2 3                      2 3 2 3 2 3 2 3
2 3 4 5 4 3 2 3      <--->           2 3 2 3 2 3 2 3
2 3 4 5 2 3 2 3                      2 3 2 3 2 3 2 3
2 3 2 3 2 3 2 3                      2 3 2 3 2 3 2 3

                      |
                      |
                     \ /
             Rect([2,2] , [3,4])
                    4 5 4
                    4 5 2-> A (2 x 3 Matrix)

Лучшее, о котором я мог думать, должно просканировать от Верхнего левого хита точку, где существует различие. Затем сканирование от Нижнего правого и поражает точка, где существует различие.

Но В худшем случае, это - O (N*M). существует ли лучший эффективный алгоритм? Или есть ли что-то, что я мог сделать с тем, как я представляю их, так, чтобы можно было применить более эффективный алгоритм? И обратите внимание, эта Матрица может быть очень большой.

9
задан SysAdmin 7 May 2010 в 05:44
поделиться

4 ответа

Нет, более эффективного алгоритма не существует. Для одинаковых матриц необходимо сканировать все элементы, поэтому алгоритм обязательно O(n*m).

3
ответ дан 4 December 2019 в 22:27
поделиться

"Но в худшем случае это O(NM). есть ли более эффективный алгоритм?". Вероятно, нет, поскольку размерность данных составляет O(NM). Многие матричные операции, подобные этой, имеют порядок MN, потому что в худшем случае есть MN элементов, которые все должны быть проверены в случае, если матрицы равны.

Рассмотрение среднего случая более интересно, если поле разности - это обязательно один прямоугольник в пределах всей матрицы, то я подозреваю, что в среднем можно обойтись сканированием меньше, чем всех элементов.

Вот что мне пришло в голову: отслеживайте текущий элемент, назовем его XY

  1. Начните с левого верхнего угла, так что XY - это верхний угол сейчас

  2. Проверьте, что элементы XY в обоих равны, если не равны, перейдите к 3, если нет, перейдите к 4

  3. Если элементы не равны, то у вас есть элемент матрицы различий. Запишите этот элемент, затем найдите в этой строке и столбце другие элементы (возможно, быстрее всего использовать что-то вроде двоичного поиска). После того, как строка/столбец будут найдены, вы получите координаты краев. Если элементы не равны, перейдите к 4.

  4. Следующим шагом переместите XY по диагонали на один элемент вниз и один элемент вправо, затем снова перейдите к 2.

  5. Как только диагональ будет пройдена, вам нужно будет проверить следующую диагональ (я подозреваю, что выбор новой диагонали, наиболее удаленной от текущей диагонали, будет лучшим, хотя у меня нет доказательств того, что это лучший выбор), пока все элементы не будут пройдены. В худшем случае это все еще O(N*M), но в среднем случае это может быть быстрее.

По сути, вы пытаетесь найти один различный элемент как можно быстрее, поэтому цель состоит в том, чтобы выбрать первый элемент таким образом, чтобы минимизировать ожидаемое значение количества поисков для нахождения первого различного элемента.

3
ответ дан 4 December 2019 в 22:27
поделиться

Я думаю, что предложенный алгоритм является оптимальным. Однако я предлагаю вам попробовать библиотеку BLAS, которая очень эффективна, и сравнить производительность. Существует также библиотека Boost uBlas, которая предоставляет интерфейс C++ и методы для матричных выражений.

0
ответ дан 4 December 2019 в 22:27
поделиться

Как отметили другие, O(N*M) является оптимальным.

Я хотел бы добавить, что при сканировании матрицы следует помнить о ее расположении в памяти. Если матрица разложена по строкам, то лучше всего сканировать по горизонтали. Если она расположена по столбцам, то лучше сканировать по вертикали. Это приведет к практически оптимальному поведению кэширования.

Конечно, это предполагает, что рассматриваемая разница действительно имеет форму прямоугольника. Если это какая-то другая форма, и вам нужен ограничивающий прямоугольник, вам придется сканировать и строки, и столбцы, независимо ни от чего.

2
ответ дан 4 December 2019 в 22:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: