2012-03-20 2 views
8

Локальный максимум в 2D массив может быть определен как значение таким образом, что все это 4 соседей меньше или равна ей, то есть для a[i][j] быть локальным максимумом,Нахождение локальных максимумов в 2D массив

a[i+1][j] <= a[i][j] 
&& a[i-1][j] <= a[i][j] 
&& a[i][j+1] <= a[i][j] 
&& a[i+1][j-1] <= a[i][j] 

Меня попросили найти все локальные максимумы в заданном двумерном массиве.

Наивный способ сделать это - просто пройти через все элементы и проверить, является ли каждый элемент локальным максимумом. Это было бы O (n^2). Я чувствую, что вы не можете сделать это лучше, хотя мой друг настаивает на том, что должен существовать асимптотически лучший алгоритм. Любые намеки?

Я думал о линиях Divide и Conquer, но я чувствую, что невозможно обнаружить все локальные максимумы, не пройдя через все числа, что обязательно будет O (n^2). Я прав, или я что-то упускаю?

+1

Если вы просто хотите один из локальных максимумов, то можно найти менее чем за n^2 раза. –

+0

@Habisoft дал лучший ответ –

ответ

-1

Я уверен, что это невозможно решить менее чем через O (n^2). Предположим, что матрица шахматной доски 2d, где все белые квадраты равны 1 и черные равны 0. Она будет иметь решения O (n^2), и для каждого решения требуется по крайней мере одно сравнение.

+0

Спасибо, ваш пример действительно проясняет все красиво :) – arya

+0

Как уже упоминалось в моем ответе, поскольку массив не указан как «квадрат», на самом деле это только «O (n)», где «n» - это общее количество элементов такой, что 'n = i * j'. Это понимание - это то, что я бы искал, если бы я был интервьюером. – Seph

+0

@arya Этот ответ неверен. рассмотрим ответ, который я предоставляю. – kasavbere

0

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

И, на мой взгляд, вы правы .. это потребует по крайней мере n^2 сравнений.

+0

Вы имеете в виду не более n^2. – kasavbere

+0

@ kasavbere- Я имел в виду, по крайней мере, только n^2. Здесь мы говорим о нижних границах. – vidit

2

Если ваш массив квадратный, ваше решение на самом деле O(I * J) не O(n^2). Строго говоря, у вас есть только N элементов в вашем 2d массиве, таким образом, это решение - O(N). Единственный способ, которым это могло быть O(n^2), - это массив, который был квадратным, так что I = J = N.

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

Худший случай, что весь массив является локальным максимумом, поскольку весь массив равен тому же значению.

Таким образом, вы должны посетить каждый элемент один раз, что делает его O(N)

Чтобы улучшить реальную производительность мира в этом вам нужно будет использовать указатели для доступа к вам массив, как и в большинстве языков 2d массивы выполняют значительно хуже, чем 1d массивы ,

+1

@ down избиратель, пожалуйста, прокомментируйте .. – Seph

0

ВАМ НЕ ПОСЕТИТЬ КАЖДЫЙ ЭЛЕМЕНТ:

Все, что вам нужно сделать, это визуализировать сетку, и вы увидите, что это может быть решена гораздо меньше, чем плоский п^2 (или I * J) , Ниже перечислены оптимизации по уровню:

1] для матрицы I * J вам нужен только поиск (I-2) * (J-2). Зачем? границы не могут быть максимумами из-за неопределенных элементов:

e.g. grid[0][J] or grid[I][0] could never be maxima. because of the -1 neighbor. 

Таким образом, для 10 по 12 сетке, вместо того, чтобы посетить все 120 элементов, мы смотрим на 80 элементов.

2] если сетка [I] [J] является максимальной, то мы можем пропустить все ячейки, смежные с [I] [J], по мере продолжения поиска. Это еще больше уменьшит количество элементов для сравнения.

Следовательно, ответ отрицательный, вам не нужно посещать каждый элемент.

+1

Пока ваши оптимизации правильны, ваш алгоритм по-прежнему будет O (i * j). Во-первых, сокращение количества проверок путем устранения границы эффективно для относительно небольших сеток (33% для 10x12), но мало для больших. На сетке 100x120 вы переходите от 12000 квадратов к 11564, что составляет <4%. Вторая оптимизация на самом деле ничего не делает в случае отсутствия локальных максимумов. – dlev

+0

Это правильно. Суть здесь заключается в том, чтобы сделать вывод так же важен, как и сам вывод. Использование ложных аргументов для получения правильных выводов не должно быть достаточно хорошим. – kasavbere

+0

Что неверно в рассуждениях? ElKamino просто завершает, на хорошем примере, и показывает, как это O (n^2). И да, вы показываете некоторые оптимизации, и я думаю, мы можем заключить, что требуемый оптимальный и полный алгоритм должен быть Θ (n^2). – rafalio

12

Только голова, локальные максимумы или минимумы 2D-сетки могут быть вычислены в O (nlgn) раз, используя стратегию разделения и завоевания. Это немного лучшая временная привязка, чем алгоритм грубой силы, содержащийся в классе сложности времени O (n^2). Кроме того, можно улучшить алгоритм разделения и покорения, чтобы получить алгоритм O (n) для поиска экстремумов 2D-сетки.

Проверьте эти заметки по теории позади такого пик собирания алгоритмов (я уверен, что их больше материалов там):

http://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf

+1

Ваше решение не находит всех локальных максимумов, только локальные максимумы. Рассмотрим матрицу I * J, содержащую только значение 5 в каждой ячейке, вам нужно будет посетить все ячейки I * J, чтобы убедиться, что в матрице нет 4 или 6. – Seph

+0

это лучший подход, чтобы пойти с –

+0

@HabiSoft ваше решение, кажется, отлично работает и решает 1D-массив в O (log n), вы также можете публиковать псевдокод для нахождения локальных максимумов в 2D-матрице, у меня проблема в его занижении просто прочитав контент. –

Смежные вопросы