Опубликован: 08.04.2009 | Уровень: для всех | Доступ: платный
Лекция 4:

Сортировка

< Лекция 3 || Лекция 4: 12345 || Лекция 5 >

4.5. Родственные сортировке задачи

4.5.1. Какова минимально возможная сложность (число сравнений в наихудшем случае) алгоритма отыскания самого тяжелого из n камней?

Решение. Очевидный алгоритм с инвариантом "найден самый тяжелый камень среди первых i " требует n-1 сравнений. Алгоритма меньшей сложности нет. Это вытекает из следующего более сильного утверждения.

4.5.2. Эксперт хочет убедить суд, что данный камень - самый тяжелый среди n камней, сделав менее n-1 взвешиваний. Доказать, что это невозможно. (Веса камней неизвестны суду, но известны эксперту.)

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

Более простое объяснение: будем следить за тем, сколько камней к данному моменту не "проиграли" (то есть не оказались легче других). Вначале их n ; при каждом взвешивании проигрывает только один камень, а если есть двое не проигравших никому, любой из них может (с точки зрения суда) оказаться самым тяжелым.

Разница между этой задачей и предыдущей: в этой задаче мы доказываем, что n-2 взвешиваний не достаточно не только для нахождения самого тяжелого, но даже для того, чтобы убедиться, что данный камень является таковым - если предположительный ответ известен. (В случае сортировки, зная предположительный ответ, мы можем убедиться в его правильности, сделав всего n-1 сравнений - каждый сравниваем со следующим по весу. Напомним, что сортировка требует в худшем случае значительно больше сравнений.)

4.5.3. Доказать, что можно найти самый легкий и самый тяжелый из 2n камней (одновременно), сделав 3n-2 взвешиваний.

Решение. Разобьем камни произвольным образом на n пар и сравним камни в каждой паре ( n взвешиваний). Отложим отдельно "победителей" (более тяжелых в своей паре) и "проигравших" (более легких). Ясно, что самый легкий камень надо искать среди проигравших ( n-1 сравнений), а самый тяжелый - среди победителей (еще n-1 сравнений).

4.5.4. Доказать, что не существует алгоритма, позволяющего гарантированно найти самый легкий и самый тяжелый среди 2n камней (одновременно), сделав менее 3n-2 взвешиваний.

Решение. Пусть такой алгоритм существует. Наблюдая за его применением к какой-то группе из 2n камней, мы будем следить за четырьмя параметрами. А именно, мы будем смотреть, сколько камней

(a) кому-то уже проиграли, а у кого-то уже выиграли;

(b) кому-то уже проиграли, но еще ни у кого не выиграли;

(c) у кого-то уже выиграли, но еще никому не проиграли;

(d) ни у кого не выиграли и никому не проиграли (то есть ни с кем не сравнивались).

(Напомним, что выигравшим в сравнении мы считаем более тяжелый камень.) Камни типа (a), очевидно, не могут уже оказаться ни самыми легкими, ни самыми тяжелыми, каковы бы ни были результаты дальнейших сравнений. Любой камень типа (b) имеет шанс оказаться самым легким (в самом деле, его можно произвольно облегчить, не меняя результатов уже выполненных сравнений), но уже не может быть самым тяжелым; для камней типа (c) наоборот. Наконец, любой камень типа (d) может быть и самым легким, и самым тяжелым.

Обозначим через a,b,c,d количества камней в соответствующих категориях и проследим, как меняются эти параметры при очередном сравнении (в зависимости от того, камни какого типа сравниваются и с каким результатом).

сравнение a b c d b+c+(3/2)d
a-a 0 0 0 0 0
a>b
a<b
0
+1
0
-1
0
0
0
0
0
-1
a<c
a>c
0
+1
+1
0
0
-1
-1
0
0
-1
a>d
a<d
0
0
+1
0
0
+1
-1
-1
-1/2
-1/2
b-b +1 -1 0 0 -1
b<c
b>c
0
+2
0
-1
0
-1
0
0
0
-2
b<d
b>d
0
+1
0
0
+1
0
-1
-1
-1/2
-3/2
c-c +1 0 -1 0 -1
c<d
c>d
+1
0
0
+1
0
0
-1
-1
-3/2
-1/2
d-d 0 +1 +1 -2 -1

Последний столбец таблицы показывает, как меняется величина \lessmskips{1mu}s=b+c+(3/2)d (которую можно рассматривать в качестве меры "оставшейся работы": камень, про который не известно ничего, с точки зрения этой меры в полтора раза сложнее камня, для которого есть односторонняя оценка). Изначально s=3n, а в конце s=2 (про все камни, кроме двух, известно, что они относятся к категории (a)). Из таблицы видно, что при любом взвешивании есть "неудачный исход", при котором s уменьшается не более чем на единицу. Такие исходы действительно возможны (не противоречат результатам предыдущих взвешиваний): при сравнении b -камня и c -камня может оказаться, что c -камень тяжелее (его вес не ограничен сверху предыдущими взвешиваниями), а при сравнении c участием d -камня результат может быть любым, поскольку про d -камень ничего не известно. (Кроме того, можно заметить, что один из исходов взвешивания невозможен, то это взвешивание вообще излишне и его можно не делать.) А если исходы всех взвешиваний неудачны, то уменьшение s с 3n до 2 потребует как минимум 3n-2 взвешиваний, что и требовалось доказать.

4.5.5. Дано n различных по весу камней. Найти самый тяжелый и второй по весу камни, сделав не более n+\lceil log_2
n\rceil-2 взвешиваний ( \lceil log_2 n\rceil - наименьшее целое k, при котором 2^k \ge n ).

Решение. Сначала найдем победителя (самый тяжелый камень), а потом будем искать второй по весу. Ясно, что второго можно искать лишь среди тех, кто проиграл лично победителю (проигравшие кому-то еще легче сразу двух камней). Если определять победителя в турнире по олимпийской системе (все делятся на пары, проигравшие выбывают, потом снова делятся на пары и так далее), то для 2^k участников понадобится k раундов, а для n участников - \lceil log_2
n\rceil раундов. В каждой игре турнира выбывает один участник, поэтому всего будет n-1 игр для определения победителя и еще \lceil log_2n\rceil-1 в турнире за второе место среди проигравших победителю.

4.5.6. Доказать, что никакой алгоритм нахождения самого тяжелого и второго по весу среди n камней не может гарантированно сделать это менее чем за n+\lceil log_2 n\rceil -2 взвешиваний.

Решение. Пусть дан такой алгоритм. В каждый момент его исполнения рассмотрим число k_i камней-участников, проигравших не менее i игр-сравнений. (Косвенные проигрыши - если a проиграл b, а b проиграл c, - не учитываются.) Легко понять, что сумма k_i по всем i равна числу игр, так как после каждой игры одно из k_i увеличивается на единицу.

Поэтому достаточно показать, что каков бы ни был алгоритм, при неудачных для него результатах игр будет выполнено неравенство k_1+k_2 \ge n + \lceil log_2 n\rceil -2. Будем называть " лидерами " тех участников, которые еще никому не проиграли. В начале их n, а в конце остается только один лидер (поскольку любой из лидеров может быть победителем). Поэтому k_1 \ge n-1 (все игроки, кроме одного, кому-то проиграли). Объясним, как надо выбирать результаты матчей, чтобы добиться неравенства k_2\ge \lceil log_2n\rceil -2. Результат встречи двух не-лидеров может быть выбран любым. Если лидер встречается с не-лидером, то выигрывает лидер. При встрече двух лидеров выигрывает более опытный, то есть тот, кто выиграл к этому моменту больше игр (при равенстве - любой).

Чтобы доказать, что в этом случае выполнено искомое неравенство на k_2, введем отношения подчинения, считая при этом, что каждый игрок в любой момент игры подчинен ровно одному лидеру. В начале каждый сам себе лидер и подчинен только себе. При встрече лидера с не-лидером (или двух не-лидеров) подчинение не меняется; при встрече двух лидеров проигравший и все его подчиненные переподчиняются выигравшему.

Легко доказать по индукции, что если лидер выиграл k игр, то группа его подчиненных (включая его самого) содержит не более 2^k человек. Вначале k=0 и в его группе только он сам. Если лидер выиграл k игр и побеждает лидера, выигравшего не более k игр, то в каждой из групп не более 2^k игроков, а в объединении не более 2^{k+1} игроков.

Следовательно, по окончании турнира лидер выиграл не менее \lceil log_2 n\rceil игр, поскольку в его группе все n игроков. Все побежденные им, кроме второго по силе игрока, проиграли еще кому-то (иначе почему мы уверены, что они не вторые по силе?). Отсюда и получается требуемая оценка на k_2.

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

Указание. Если по окончанию турнира определился второй по силе игрок, то он кому-то проиграл (откуда мы знаем иначе, что он не первый?), и тем самым известен и победитель.

4.5.8. Дано n различных по весу камней и число k (от 1 до n ). Требуется найти k -ый по весу камень, сделав не более Cn взвешиваний, где C - некоторая константа, не зависящая от k и n.

Замечание. Сортировка позволяет сделать это за \text{Cn log n} взвешиваний. Указание к этой (трудной) задаче приведено в лекции про рекурсию.

Следующая задача имеет неожиданно простое решение.

4.5.9. Имеется n одинаковых на вид камней, некоторые из которых на самом деле различны по весу. Имеется прибор, позволяющий по двум камням определить, одинаковы они или различны (но не говорящий, какой тяжелее). Известно, что среди этих камней большинство (более n/2 ) одинаковых. Сделав не более n взвешиваний, найти хотя бы один камень из этого большинства. (Предостережение. Если два камня одинаковые, это не гарантирует их принадлежности к большинству.)

Указание. Если найдены два различных камня, то их оба можно выбросить - хотя бы один из них плохой и большинство останется большинством.

Решение. Программа просматривает камни по очереди, храня в переменной i число просмотренных камней. (Считаем камни пронумерованными от 1 до n.) Помимо этого программа хранит номер "текущего кандидата" c и его "кратность" k. Смысл этих названий объясняется инвариантом (И):

если к непросмотренным камням (с номерами i+1...n ) добавили бы k копий c -го камня, то наиболее частым среди них был бы такой же камень, что и для исходного массива.

Получаем такую программу:

k:=0; i:=0;
{(И)}
while i<>n do begin
| if k=0 then begin
| | k:=1; c:=i+1; i:=i+1;
| end else if (i+1-ый камень одинаков с c-ым) then begin
| | i:=i+1; k:=k+1;
| |  {заменяем материальный камень идеальным}
| end else begin
| | i:=i+1; k:=k-1;
| | {выкидываем один материальный и один идеальный камень}
| end;
end;
искомым является c-ый камень

Замечание. Поскольку во всех трех вариантах выбора стоит команда i:=i+1, ее можно вынести наружу.

Заметим также, что эта программа гарантирует отыскание наиболее частого камня, лишь если он составляет большинство.

Следующая задача не имеет на первый взгляд никакого отношения к сортировке.

4.5.10. Имеется квадратная таблица a[1..n,1..n]. Известно, что для некоторого i строка с номером i заполнена одними нулями, а столбец с номером i - одними единицами (за исключением их пересечения на диагонали, где стоит неизвестно что). Найти такое i (оно, очевидно, единственно). Число действий порядка n. (Заметим, что это существенно меньше числа элементов в таблице.)

Указание. Рассмотрите a[i][j] как результат "сравнения" i с j и вспомните, что самый тяжелый из n камней может быть найден за n сравнений. (Заметим, что таблица может не быть "транзитивной", но все равно при "сравнении" двух элементов один из них отпадает.)

< Лекция 3 || Лекция 4: 12345 || Лекция 5 >
Татьяна Новикова
Татьяна Новикова
Россия, Пошатово
Artem Bardakov
Artem Bardakov
Россия