Примеры алгоритмов и доказательств, которые кажутся правильными, но не являются

15

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

Существуют ли классические примеры алгоритмов, которые выглядят правильно, но не так? Я ищу случаи, когда подход Initialization-Maintenance-Termination улавливает то, чего нет на первый взгляд.

Marin
источник
5
Возможно, интерес: cs.stackexchange.com/q/29475/755
DW
5
Проголосую, потому что считаю, что это очень важный педагогический вопрос. Это немного выходит за рамки cstheory, но я не знаю лучшей платформы для него, и в сообществе cstheory есть много инструкторов по алгоритмам. В большинстве курсов по разработке алгоритмов учащиеся могут только корректировать существующие алгоритмы и решать проблемы, которые легко решить с помощью известных методов. Это укрепляет впечатление, настолько привлекательное для студентов, что можно смело доверять интуитивному ощущению правильности, казалось бы, правдоподобного алгоритма. Хороший курс по разработке алгоритмов должен делать обратное!
Нил Янг
3
Я хотел бы иметь такую ​​коллекцию.
Чандра Чекури

Ответы:

20

2D локальный максимум

вход: двумерный массив An×nA

вывод: локальный максимум - пара такая, что A [ i , j ] не имеет соседней ячейки в массиве, который содержит строго большее значение. (i,j)A[i,j]

(Соседние ячейки есть среди , которые присутствуют в массиве.) Так, например, если являетсяA[i,j+1],A[i,j1],A[i1,j],A[i+1,j]A

0134323125014013

тогда каждая ячейка с полужирным шрифтом является локальным максимумом. Каждый непустой массив имеет хотя бы один локальный максимум.

Алгоритм. Существует алгоритм времени : просто проверьте каждую ячейку. Вот идея более быстрого, рекурсивного алгоритма.O(n2)

Для определите крест X, состоящий из ячеек в среднем столбце и ячеек в среднем ряду. Сначала проверьте каждую ячейку в X , чтобы увидеть , если ячейка является локальным максимумом в A . Если так, верните такую ​​ячейку. В противном случае, пусть ( i , j ) будет ячейкой в X с максимальным значением. Поскольку ( i , j ) не является локальным максимумом, он должен иметь соседнюю ячейку ( i , j ) с большим значением.AXXA(i,j)X(i,j)(i,j)

Разбиение (массив A , минус ячейки в X ) на четыре квадранта - верхний левый, верхний правый, нижний левый и нижний правый квадранты - естественным образом. Соседняя ячейка ( i , j ) с большим значением должна находиться в одном из этих квадрантов. Назовите этот квадрант A . AXAX(i,j)A

Лемма. Quadrant ' содержит локальный максимум A .AA

Доказательство. Рассмотрим начало с ячейки . Если это не локальный максимум, перейдите к соседу с большим значением. Это может повторяться до достижения ячейки, которая является локальным максимумом. Эта последняя ячейка должна быть в A , поскольку A ограничен со всех сторон ячейками, значения которых меньше значения ячейки ( i , j ) . Это доказывает лемму. (i,j)AA(i,j)

Алгоритм вызывает себя рекурсивно на подмассиваA',чтобы найти там локальный максимум(i,j), затем возвращает эту ячейку.n2×n2A(i,j)

Время работы для матрицы n × n удовлетворяет T ( n ) = T ( n / 2 ) + O ( n ) , поэтому T ( n ) = O ( n ) . T(n)n×nT(n)=T(n/2)+O(n)T(n)=O(n)

Таким образом, мы доказали следующую теорему:

Теорема. Существует алгоритм времени для нахождения локального максимума в массиве n × n .O(n)n×n

Или мы?

Нил Янг
источник
При первом чтении единственной ошибкой, которую я обнаружил, было решение повторения. Это единственная ошибка?
Раду GRIGore
1
Повторение верно. Алгоритм нет!
Нил Янг
1
Ах да, я сделал глупую ошибку с повторением. Я вижу проблему: максимум, который вы доказываете, существует (не обязательно), что вы находите. И то, что вы находите, игнорирует X.
Раду ГРИГОР
3
(2143300101230001023002222222333233300323000032300)
2
AA