Россия, Пошатово |
Переменные, выражения, присваивания
1.2.20. Даны два массива и . "Соединить" их в массив ( ; каждый элемент должен входить в массив z столько раз, сколько раз он входит в общей сложности в массивы x и y ). Число действий порядка m.
Решение.
k1 := 0; l1 := 0; {инвариант: ответ получится, если к z[1]..z[k1+l1] добавить справа соединение массивов x[k1+1]..x[k] и y[l1+1]..y[l]} while (k1 <> k) or (l1 <> l) do begin | if k1 = k then begin | | {l1 < l} | | l1 := l1 + 1; | | z[k1+l1] := y[l1]; | end else if l1 = l then begin | | {k1 < k} | | k1 := k1 + 1; | | z[k1+l1] := x[k1]; | end else if x[k1+1] <= y[l1+1] then begin | | k1 := k1 + 1; | | z[k1+l1] := x[k1]; | end else if x[k1+1] >= y[l1+1] then begin | | l1 := l1 + 1; | | z[k1+l1] := y[l1]; | end else begin | | { такого не бывает } | end; end; {k1 = k, l1 = l, массивы соединены}
Этот процесс можно пояснить так. Пусть у нас есть две стопки карточек, отсортированных по алфавиту. Мы соединяем их в одну стопку, выбирая каждый раз ту из верхних карточек обеих стопок, которая идет раньше в алфавитном порядке. Если в одной стопке карточки кончились, берем их из другой стопки.
1.2.21. Даны два массива и . Найти их " пересечение", то есть массив содержащий их общие элементы, причем кратность каждого элемента в массиве z равняется минимуму из его кратностей в массивах x и y. Число действий порядка .
1.2.22. Даны два массива и и число q. Найти сумму вида , наиболее близкую к числу q. (Число действий порядка k+l, дополнительная память - фиксированное число целых переменных, сами массивы менять не разрешается.)
Указание. Надо найти минимальное расстояние между элементами и , что нетрудно сделать в ходе их слияния в один (воображаемый) массив.
1.2.23. (из книги Д. Гриса) Некоторое число содержится в каждом из трех целочисленных неубывающих массивов , , . Найти одно из таких чисел. Число действий должно быть порядка .
Решение.
p1:=1; q1=1; r1:=1; {инвариант: x[p1]..x[p], y[q1]..y[q], z[r1]..z[r] содержат общий элемент} while not ((x[p1]=y[q1]) and (y[q1]=z[r1])) do begin | if x[p1]<y[q1] then begin | | p1:=p1+1; | end else if y[q1] <z[r1] then begin | | q1:=q1+1; | end else if z[r1] <x[p1] then begin | | r1:=r1+1; | end else begin | | { так не бывает } | end; end; {x[p1] = y[q1] = z[r1]} writeln (x[p1]);
1.2.24. Та же задача, только заранее не известно, существует ли общий элемент в трех неубывающих массивах и требуется это выяснить (и найти один из общих элементов, если они есть).
1.2.25. Элементами массива a[1..n] являются неубывающие массивы [1..m] целых чисел:
Известно, что существует число, входящее во все массивы a[i] (существует такое x, что для всякого i из 1..n найдется j из 1..m, для которого ). Найти одно из таких чисел х.Решение. Введем массив , отмечающий начало "остающейся части" массивов .
for k:=1 to n do begin | b[k]:=1; end; eq := true; for k := 2 to n do begin | eq := eq and (a[1][b[1]] = a[k][b[k]]); end; {инвариант: оставшиеся части пересекаются, т.е. существует такое х, что для всякого i из [1..n] найдется j из [1..m], не меньшее b[i], для которого a[i][j] = х; eq <=> первые элементы оставшихся частей равны} while not eq do begin | s := 1; k := 1; | {a[s][b[s]] - минимальное среди a[1][b[1]]..a[k][b[k]]} | while k <> n do begin | | k := k + 1; | | if a[k][b[k]] < a[s][b[s]] then begin | | | s := k; | | end; | end; | {a[s][b[s]] - минимальное среди a[1][b[1]]..a[n][b[n]]} | b [s] := b [s] + 1; | for k := 2 to n do begin | | eq := eq and (a[1][b[1]] = a[k][b[k]]); | end; end; writeln (a[1][b[1]]);
1.2.26. Приведенное решение предыдущей задачи требует порядка действий. Придумать способ с числом действий порядка mn.
Указание. Придется пожертвовать симметрией и выбрать одну из строк за основную. Двигаясь по основной строке, поддерживаем такое соотношение: во всех остальных строках отмечен максимальный элемент, не превосходящий текущего элемента основной строки.