Корректность жадного алгоритма

В неубывающей последовательности (положительных) целых чисел можно удалить два элемента, если введите сюда описание изображения. Сколько пар максимум можно удалить из этой последовательности?

Поэтому я подумал о следующем решении:

  • Беру заданную последовательность и делю на две части (первую и вторую).
  • Каждому из них присваиваем итератор - it_first := 0 и it_second := 0 соответственно. количество: = 0
  • when it_second != second.length
    • if 2 * first[it_first] <= second[it_second]
      • count++, it_first++, it_second++
    • else
      • it_second++
  • считать это ответ

Пример:

количество: = 0

[1,5,8,10,12,13,15,24] --> первый := [1,5,8,10], второй := [12,13,15,24]

  1. 2 * 1 ?‹ 12 --> true, count++, it_first++ и it_second++

  2. 2 * 5 ?‹ 13 --> true, count++, it_first++ и it_second++

  3. 2 * 8 ?‹ 15 --> ложь, it_second++

  4. 8 ?‹24 --> верно, count ++it_second достигает последнего элемента - END.

  5. количество == 3

Линейная сложность (наихудший случай, когда нет таких удаляемых элементов. n/2 элементов сравниваются с n/2 элементами). Так что моя недостающая часть - это «правильность» алгоритма - я читал о доказательстве жадных алгоритмов - но в основном с деревьями, и я не могу найти аналогию. Любая помощь будет оценена по достоинству. Спасибо!

РЕДАКТИРОВАТЬ: Под правильностью я подразумеваю: * Это работает * Это нельзя сделать быстрее (в журнале или константе)

Хотелось бы поставить немного графики, но из-за очков репутации ‹ 10 - не могу. (я имел в виду один латекс в начале ;))


person lemoid    schedule 11.03.2015    source источник
comment
Ваш подход не будет охватывать все случаи. Представьте себе [1, 2, 4, 9]. [4, 9] тоже может быть такой парой. Или, как в вашем примере, такой парой может быть [12, 24].   -  person Harsh Gupta    schedule 12.03.2015
comment
Это не имеет значения. Мы спрашиваем, сколько максимум пар можно удалить.   -  person lemoid    schedule 12.03.2015
comment
Ок, я пропустил это.   -  person Harsh Gupta    schedule 12.03.2015
comment
Вы должны написать функцию для вычисления этого с учетом входной последовательности, или вы теоретически спрашиваете, с последовательностью n неубывающих чисел, какое максимальное количество пар можно удалить?   -  person Broseph    schedule 12.03.2015
comment
Чтобы быть точным, если исходный список имеет нечетное количество записей, войдет ли дополнительная запись в первую или вторую последовательность?   -  person user3386109    schedule 12.03.2015
comment
Не могли бы вы подробнее рассказать о «правильности» алгоритма? Вы имеете в виду решение, которое дает жадный алгоритм?   -  person Dragos Rizescu    schedule 12.03.2015
comment
(второй) Я спрашиваю, как доказать правильность алгоритма. Я имею в виду: это невозможно сделать лучше (за постоянное время или логин) и всегда находит хорошее решение. Извините, если я не объяснил это ясно.   -  person lemoid    schedule 12.03.2015
comment
@DragosRizescu - я имею в виду решение, которое дает мой жадный алгоритм.   -  person lemoid    schedule 12.03.2015
comment
Моей первой попыткой будет доказательство от противного.   -  person greybeard    schedule 12.03.2015


Ответы (2)


  1. Правильность:

    • Предположим, что максимальное количество пар, которые можно удалить, равно k. Утверждение: существует оптимальное решение, в котором первые элементы всех пар являются k наименьшими элементами массива. Доказательство: я покажу, что любое решение можно преобразовать в такое, которое содержит первые k элементов в качестве первых элементов всех пар.

      1. Предположим, что у нас есть две пары (a, b), (c, d) такие, что a <= b <= c <= d, 2 * a <= b и 2 * c <= d. В этом случае также допустимы пары (a, c) и (b, d). И теперь у нас есть a <= c <= b <= d. Таким образом, мы всегда можем преобразовать пары так, чтобы первый элемент любой пары не был больше второго элемента любой пары.

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

    • Теперь мы знаем, что существует оптимальное решение, содержащее k наименьших элементов. Понятно, что мы не можем ухудшить ответ, взяв наименьший неиспользуемый элемент (увеличение его может только уменьшить ответ для следующих элементов), который подходит каждому из них. Таким образом, это решение является правильным.

    • Замечание на случай, когда длина массива нечетная: неважно, куда идет средний элемент: в первую или во вторую половину. В первой половине бесполезно(во второй половине не хватает элементов). Если ставить на вторую половину, то это бесполезно два(допустим, что взяли. Это значит, что где-то во второй половине есть "свободное место". Таким образом, мы можем сдвинуть некоторые элементы на единицу и избавиться от него ).

  2. Оптимальность с точки зрения временной сложности: временная сложность этого решения равна O(n). Мы не можем найти ответ, не прочитав весь ввод в худшем случае, а чтение занимает уже O(n) времени. Таким образом, данный алгоритм является оптимальным.

person kraskevich    schedule 11.03.2015
comment
Это очень здорово. Надеюсь, вам понравилось это. Благодарю вас! - person lemoid; 12.03.2015
comment
Ну, я думаю, я могу перестать печатать свой ответ :) - person Jeremy West; 12.03.2015
comment
На самом деле, мы можем сделать более сильное утверждение: если существует допустимый ответ длины k, ответ, принимающий первые k значений и соединяющий их с последними k значениями, является допустимым. Однако использование более сильного утверждения не кажется более простым, чем выполнение предложенного алгоритма. - person Gassa; 12.03.2015
comment
@Gassa Именно такой подход я и планировал. Я действительно думаю, что на самом деле это делает доказательство немного яснее. Но неясно, упрощает ли это алгоритм. - person Jeremy West; 12.03.2015
comment
@JeremyWest То же самое здесь :) - person Gassa; 12.03.2015
comment
(Важность 2. заключается в том, что алгоритм, дающий правильный результат, заканчивается.) - person greybeard; 12.03.2015

Предположим ваш метод. Индексы отсчитываются от 0.

Обозначим в общем:

  • end_1 = floor(N/2) граница (включительно) первой части.

Обозначим при итерации:

  • i индекс в первой части, j индекс во второй части,
  • оптимальное решение до этого момента sol(i,j) (используя алгоритм спереди),
  • пары, которые остаются оптимально спаренными за (i,j) точкой, т. е. от (i+1,j+1) и далее rem(i,j) (можно рассчитать с помощью алгоритма сзади),
  • окончательное оптимальное решение может быть выражено как функция любой точки как sol(i,j) + rem(i,j).

Наблюдение №1: при выполнении алгоритма спереди используются все точки из [0, i] диапазона, некоторые точки из [end_1+1, j] диапазона не используются (мы пропускаем a(j) не достаточно большой). При выполнении алгоритма сзади некоторые [i+1, end_1] точек не используются, а используются все [j+1, N] точек (недостаточно малое a(i) пропускаем).

Наблюдение №2: rem(i,j) >= rem(i,j+1), потому что rem(i,j) = rem(i,j+1) + M, где M может быть 0 или 1 в зависимости от того, можем ли мы соединить a(j) с каким-то неиспользуемым элементом из диапазона [i+1, end_1].

Аргумент (от противного): предположим, что 2*a(i) <= a(j) и что отсутствие объединения a(i) и a(j) в пару дает как минимум такое же хорошее окончательное решение. Далее по алгоритму мы попытаемся соединить a(i) и a(j+1) в пары. С:

  • rem(i,j) >= rem(i,j+1) (см. выше),
  • sol(i,j+1) = sol(i,j) (поскольку мы не объединили a(i) и a(j) в пару)

мы получаем, что sol(i,j) + rem(i,j) >= sol(i,j+1) + rem(i,j+1) что противоречит предположению.

person plesiv    schedule 11.03.2015