Интуиция
Для каждого элемента ar2[i]
из ar2
(т.е. внутри внешнего цикла) в основном вы находите индекс j
в ar1
таким образом, что все элементы ar1
в диапазоне [(j+1), (m-1)]
больше, чем ar2[i]
. Затем вы берете наименьший элемент в этом диапазоне и отбрасываете его из ar1
в ar2
, а именно в ячейку с индексом i
, где когда-то находилось значение в ar2[i]
перед переносом в ar1
.
Причиной переноса ar2[i]
в ar1[j+1]
является попытка собрать наименьшие m элементов в ar1
, а остальные - в ar2
. Вероятно, элегантная вещь, которую делает этот алгоритм, — это обход ar2
справа налево. Если вы помните, что и ar1
, и ar2
отсортированы, переход справа налево в ar2
помогает достичь используя постоянное дополнительное пространство следующим образом.
Когда вы идете справа налево по ar2
, вы сталкиваетесь с уменьшением или, по крайней мере, с невозрастанием значений в ar2[i]
. Это означает, что вы найдете уменьшающиеся или не возрастающие значения ar1[m-1]
, чтобы заменить их. По сути, наименьшие элементы ar1[m-1]
больше ar2[i]
не будут увеличиваться, поскольку значение ar2[i]
уменьшается при движении справа налево.
Следовательно, элементы, которые мы сбрасываем с ar1
на arr2
в каждой итерации внешнего цикла, также будут в невозрастающем или убывающем порядке, и мы будем помещать их в индексы в порядке убывания, сохраняя порядок ar2
.
Инвариантный подход
Возможным, хотя и довольно неформальным инвариантом может быть то, что ar1
и ar2
будут сортироваться после каждой итерации, причем не более одного элемента ar2
, скажем, ar2[i]
, для которого существует по крайней мере 1 ar1[k]>ar2[i]
, заменяется на элемент в ar1
таким образом, чтобы не нарушать порядок сортировки любого массива.
Изначально элементы упорядочены. После каждой итерации, если существует элемент меньше ar2[i]
в ar1
с индексом j
, весь диапазон больше ar2[i]
сдвигается вправо на 1. ar2[i]
помещается в ar1[j+1]
так, чтобы не нарушался порядок ar1
. Затем ранее последний элемент ar1
, который больше не помещается в ar1
, помещается в ar2[i]
.
Легко видеть, что порядок ar1
сохраняется на каждой итерации внешнего цикла. Приказ ar2
требует немного больше внимания.
Каждый раз, когда мы помещаем элемент ar2
в ar1
, мы знаем, что ранее последний элемент ar1
, который мы помещаем в ar2
(т.е. вместо ar2[i]
), больше, чем ar2[i]
, поскольку он больше или равен ar1[j+1]
, который был больше, чем ar2[i]
. (ar2[i] < ar1[j+1] <= last
)
Кроме того, все ранее замененные элементы в ar2
(т. е. элементы справа от i-го индекса ar2
) были заменены значениями last, которые были больше или равны значению last в текущей итерации, поскольку Изначально был заказан ar1
.
Следовательно, после каждой итерации ar2
также остается упорядоченным, а после завершения алгоритма не существует элемента ar2[i]
такого, что был бы элемент ar1[k] > ar2[i]
.
person
ilim
schedule
28.03.2016