Обработка данных за один проход 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Обработка данных за один проход



а. Максимум

б. Второй максимум

в. Пропущено одно из чисел от 1 до N. Какое?

г. Все числа, кроме одного, встречаются по 2 раза.

д*. Больше половины элементов массива - одинаковые

Суммы на подотрезках

а. Частичные суммы

б. Сумма каждых K соседних чисел

в. Подотрезок с максимальной суммой

Два указателя

а. Подотрезок с заданной суммой, натуральные числа

б. Стильная одежда

Стек и очередь

а. Стек с поддержкой минимума

б. Реализация очереди на двух стеках

в. Очередь с поддержкой минимума

г. Минимум каждых К соседних чисел

Скобочные последовательности, баланс

а. Правильная скобочная последовательность из круглых скобок

б. Удалите скобки

в. Слишком вложенные скобки

г. Правильная скобочная последовательность из трёх видов скобок

Одномерная динамика

а. Мячик на лесенке

b. Покупка билетов

События: совместная сортировка начал и концов

Рекурсивные” алгоритмы линейной сложности

а. Нахождение медианы

б. Нахождение k-го максимума

Рекурсивный перебор

Важную роль среди алгоритмов играют алгоритмы перебора различных комбинаторных структур. Например, можно перебирать все подмножества данного множества, все подмножества, содержащие заданное число элементов, все перестановки данного набора элементов. Основным способом перебора комбинаторных структур является рекурсия.

ПЕРЕБОР ВСЕХ ПОДМНОЖЕСТВ

Пусть дано некоторое множество, содержащее n элементов a0, a1, …, an−1. Необходимо перебрать все его подмножества. Общее число подмножеств n-элементного множества равно 2n. Например, у множества из 3 элементов {1,2,3} восемь подмножеств: {} (пустое подмножество), {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}.

Каждое подмножество будем кодировать строкой из n символов, где i-й символ будет равен 0, если aiне входит в выбранное подмножество, или равен 1, если ai входит в выбранное подмножество. То есть строка из одних нулей соответствует пустому множеству, а строка из одних единиц соответствует подмножеству, совпадающему со всем множеством.

Таким образом, задача сводится к перебору всех двоичных строк (т. е. состоящих из символов 0 или 1) длины n. Строки будем перебирать в лексикографическом порядке, то есть для n=3 порядок будет таким:

000
001
010
011
100
101
110
111

В лексикографическом порядке все строки упорядочены по первому символу, т. е. сначала нужно вывести те строки, у которых первый символ равен 0, затем те строки, у которых первый символ равен 1. Те строки, у которых первые символы равны, упорядочены по второму символу, затем - по третьему и т. д.

Если посмотреть на пример для n=3 то можно видеть, что результат перебора построен по следующему принципу. Сначала нужно взять первый символ строки равный 0, затем к нему всеми возможными способами дописать следующие n−1 символ также в лексикографическом порядке. Потом поставим на первое место символ, равный 1 и допишем к нему всеми возможными способами следующие n−1 символ.

В свою очередь, если у нас уже есть какая-то сформированная начальная часть строки (например, первый символ равен 0), то нужно к нему добавить сначала символ 0 (получим начальную часть вида 00) и так же рекурсивно дописать оставшиеся n−2 символа, затем добавить символ 1 (получим начальную часть вида 01), и рекурсивно добавить к этой начальной части еще n−2 символа.

Решение оформим в виде рекурсивной функции generate с двумя параметрами. Первый параметр — число n равное количеству символов строки, которые нужно сгенерировать. Второй параметр — строка prefix, в которой хранится уже сгенерированная начальная часть строки. Функция будет добавлять по одному символу к уже построенной части prefix, сначала добавляя символ «0», затем символ «1», после чего функция будет рекурсивно вызывать себя для построения n−1 оставшегося символа.

Окончание рекурсии: случай n=0, в этом случае функция больше не должна ничего строить и должна вывести построенную строку, которая целиком будет храниться в переменной prefix. Если требуется не вывести полученные строки на экран, а как-то обработать данное подмножество, то вместо функции print нужно вызвать функцию обработки подмножества.

Во всех остальных случаях функция дважды вызывает себя рекурсивно для построения строки длины n−1 - сначала добавив к строке prefix «0», затем добавив «1». Функция может быть реализована следующим образом:

def generate(n, prefix):
if n == 0:
print(prefix)
else:
generate(n - 1, prefix + "0")
generate(n - 1, prefix + "1")

Для того, чтобы вывести все двоичные строки длины 5, нужно вызвать эту функцию так:

generate(5, "")

Попробуем модифицировать эту функцию. Допустим, нужно вывести все двоичные строки, в которых нет двух символов «1» подряд. Это означает, что добавить символ «1» можно только в том случае, если prefix оканчивается на символ «0», а также в случае пустой строки. Нужно добавить только одно условие:

def generate(n, prefix):
if n == 0:
print(prefix)
else:
generate(n - 1, prefix + "0")
if prefix == "" or prefix[-1] == "0":
generate(n - 1, prefix + "1")



Поделиться:


Последнее изменение этой страницы: 2017-02-19; просмотров: 466; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.149.230.44 (0.038 с.)