Получение предыдущего объекта — различия между версиями
Flanir (обсуждение | вклад) (→Специализация алгоритма для генерации предыдущего разбиения на слагаемые) |
Flanir (обсуждение | вклад) (→Специализация алгоритма для генерации предыдущего сочетания) |
||
Строка 63: | Строка 63: | ||
'''return''' ''null'' | '''return''' ''null'' | ||
== Специализация алгоритма для генерации предыдущего сочетания == | == Специализация алгоритма для генерации предыдущего сочетания == | ||
− | + | ||
+ | |||
+ | * Проходя справа налево, находим элемент <tex>t</tex> так, чтобы его разница со следующим отличалась более чем на единицу | ||
* уменьшаем его на единицу | * уменьшаем его на единицу | ||
* дописываем максимально возможный хвост | * дописываем максимально возможный хвост | ||
Строка 81: | Строка 83: | ||
'''return''' a | '''return''' a | ||
'''return''' null | '''return''' null | ||
+ | {|align="left" | ||
+ | |-valign="bottom" | ||
+ | |[[Файл:PrevChoose.png|600px|thumb|сочетания из n по k, элемент, который уменьшаем, максимальный хвост, преобразование]] | ||
+ | |} | ||
== Специализация алгоритма для генерации предыдущего разбиения на слагаемые == | == Специализация алгоритма для генерации предыдущего разбиения на слагаемые == |
Версия 21:52, 30 декабря 2014
Содержание
- 1 Алгоритм
- 2 Специализация алгоритма для генерации предыдущего битового вектора
- 3 Специализация алгоритма для генерации предыдущей перестановки
- 4 Специализация алгоритма для генерации предыдущей мультиперестановки
- 5 Специализация алгоритма для генерации предыдущего сочетания
- 6 Специализация алгоритма для генерации предыдущего разбиения на слагаемые
- 7 См. также
Алгоритм
Определение: |
Получение предыдущего объекта — это нахождение объекта, предшествующего данному в лексикографическом порядке. |
Объект
называется предыдущим за , если и не найдется такого , что .Отсюда понятен алгоритм:
- Находим суффикс минимальной длины, который можно изменить без изменения префикса текущего объекта
- К оставшейся части дописываем максимально возможный элемент (чтобы было выполнено правило )
- Дописываем максимально возможный хвост
По построению получаем, что
— минимально возможный.Специализация алгоритма для генерации предыдущего битового вектора
- Находим минимальный суффикс, в котором есть , его можно уменьшить, не изменяя оставшейся части
- Вместо записываем
- Дописываем максимально возможный хвост из единиц
int[] prevVector(int[] a): //
— длина вектора
while (n >= 0) and (a[n] != 1)
a[n] = 1
n--
if n == -1
return null
a[n] = 0
return a
Приведённый алгоритм эквивалентен вычитанию единицы из битового вектора.
Специализация алгоритма для генерации предыдущей перестановки
- Двигаясь справа налево, находим элемент, нарушающий убывающую последовательность
- Меняем его с максимальным элементом, меньшим нашего, стоящим правее
- Перевернем правую часть
int[] prevPermutation(int[] a): //
— длина перестановки
for i = n - 2 downto 0
if a[i] > a[i + 1]
max = i + 1
for j = i + 1 to n - 1
if (a[j] < a[max]) and (a[j] < a[i])
max = j
swap(a[i], a[j])
reverse(a, i + 1, n - 1)
return a
return null
Специализация алгоритма для генерации предыдущей мультиперестановки
Алгоритм полностью аналогичен генерации предыдущей перестановки
- Двигаясь справа налево, находим элемент, нарушающий убывающую последовательность
- Меняем его с максимальным элементом, меньшим нашего, стоящим правее
- Перевернем правую часть
int[] prevMultipermutation(int[] a): //
— длина перестановки
for i = n - 2 downto 0
if a[i] > a[i + 1]
max = i + 1
for j = i + 1 to n - 1
if (a[j] < a[max]) and (a[j] < a[i])
max = j
swap(a[i], a[j])
reverse(a, i + 1, n - 1)
return a
return null
Специализация алгоритма для генерации предыдущего сочетания
- Проходя справа налево, находим элемент так, чтобы его разница со следующим отличалась более чем на единицу
- уменьшаем его на единицу
- дописываем максимально возможный хвост
Если элемента
не существует, значит было дано первое сочетание. А значит и предыдущего сочетания не существует.Пусть массив
хранит сочетания так, что первый элемент хранится вint[] prevChoose(int[] a): //— количество различных элементов a[0] = 0 // — длина сочетания for i = k downto 1 if a[i] - a[i - 1] > 1 a[i]-- t = max(a[i] + 1, n - (k - i) + 1) for j = i + 1 to k a[j] = t t++ return a return null
Специализация алгоритма для генерации предыдущего разбиения на слагаемые
Рассматриваемый алгоритм находит предыдущее разбиение на слагаемые, при этом разбиение упорядочено по возрастанию.
Рассмотрим два случая:
Последнее слагаемое можно разбить на два таких, отличающихся не более, чем на 1, так чтобы наименьшее из них было больше предпоследнего слагаемого в разбиении. Тогда вместо последнего слагаемого мы запишем два найденных слагаемых.
Если невозможен первый случай, то найдем такое слагаемое (не последнее), которое точно больше предыдущего на 1. Обозначим его номер за . Тогда , а . А будет последним слагаемым в разбиении.
Пример:
Случай 1.
Случай 2.
Реализация
Первое слагаемое находится под индексом 1.
list<int> prevPartition(list<int> a): a[0] = 0 if a[a.size] / 2 >= a[a.size - 1] k = a[a.size] a[a.size] = a[a.size] / 2 a.push_back(k - a[a.size - 1]) return a else sum = a[n]; for i = a.size downto 1 if (i == 1) and (a[1] == 1) return null if a[i] > a[i - 1] a[i]-- a[i + 1] = sum + 1 n = i + 1 return a else sum +=a[i] a.pop_back();