avva: (Default)
[personal profile] avva
Хорошая программистская задачка:

Дан список с данными. И есть подозрение, что более половины элементов в списке - это один и тот же элемент (число, например). Требуется определить, так ли это, и если так — то что это за элемент и сколько раз он встречается. За линейное время и без дополнительной памяти. (кроме константы).

Ссылку на журнал, из которого взял, дам позже, т.к. в нём есть решение.

P.S. Есть разные способы решения (я нашёл один из них, но не лучший, как потом узнал). Если из алгоритма неочевидно, что он всегда работает, нужно это доказать, иначе решение неполное.
Page 1 of 4 << [1] [2] [3] [4] >>

Date: 2004-07-11 06:30 pm (UTC)
From: [identity profile] flashkot.livejournal.com
можно ли модифицировать список данных (сортировать)?

Date: 2004-07-11 06:36 pm (UTC)
From: [identity profile] avva.livejournal.com
Всё равно ведь невозможно отсортировать за линейное время.
Но в принципе в условии задачи не сказано, можно ли модифицировать список. Ясно, что лучше обойтись без модификации, но я не скажу, можно без неё обойтись или нельзя ;)

Date: 2004-07-11 06:44 pm (UTC)
From: [personal profile] alll
Нельзя ли уточнить, что значит "без дополнительной памяти. (кроме константы)." Константным подразумевается число дополнительных переменных или ничем кроме исходного массива и некоей константы нельзя пользоваться? Или нечто иное?

Date: 2004-07-11 06:47 pm (UTC)
From: [identity profile] avva.livejournal.com
Размер дополнительной памяти, которой можно пользоваться - константа, т.е. не зависит от размера исходного списка. Это может быть какое-то фиксированное число дополнительных переменных, или дополнительный массив фиксированного размера, итп.

Date: 2004-07-11 06:49 pm (UTC)
From: [identity profile] french-man.livejournal.com
Да, меня это тоже смутило. Уже "сколько раз встречается" - число, для записи которого константы не хватит.

Date: 2004-07-11 06:49 pm (UTC)
From: [identity profile] flashkot.livejournal.com
если сортировать нельзя, то мне кроме тупого перебора ничего в голову не лезет...

красивого и быстрого решения придумать не могу... в математике не силён... (:

Date: 2004-07-11 06:50 pm (UTC)
From: [identity profile] french-man.livejournal.com
Да, но под каждую переменную сколько можно отвести?

Date: 2004-07-11 06:57 pm (UTC)
From: [identity profile] french-man.livejournal.com
Как я понимаю, точная формулировка должна быть примерно такой: "под дополнительную память можно отвести не более чем О(log n) бит, где n - длина списка".

Date: 2004-07-11 06:58 pm (UTC)
From: [identity profile] avva.livejournal.com
Гм. Сразу видно математика ;)
Можно предположить, что размер списка и все релевантные величины умещаются, скажем, в 32 бита. Т.е. переменная, подсчитывающая размер массива, считается занимающей фиксированное количество памяти. То же самое касается переменной, хранящей копию элемента списка.

(при этом, естественно, воспользоваться этим как лазейкой и объявить "фиксированный" дополнительный массив размером в 2^32, или, ещё удобнее, в 2^N, где N - количество битов для записи каждого элемента, не разрешается. Если надо быть совсем точным, можно разрешить память, кол-во которой равно линейной функции от суммы кол-ва битов для представления элемента и кол-ва битов для представления размера массива. Но на практике никто так не делает и просто говорят о константной памяти).

Date: 2004-07-11 07:21 pm (UTC)
From: [identity profile] dmitryle.livejournal.com
Если такое число существует, то оно median (как оно по-русски называется?). Говорят (в сети), что есть линейный метод нахождения median. Находим (за линейное время) и проверяем (также за линейное время).

Date: 2004-07-11 07:27 pm (UTC)
From: [identity profile] french-man.livejournal.com
Сумма квадратична, извините.

Date: 2004-07-11 07:30 pm (UTC)
From: [personal profile] alll
А, ну да, вычеркиваем :)

Date: 2004-07-11 07:33 pm (UTC)
From: [identity profile] avva.livejournal.com
Остроумно! ;-)

Но требует дополнительной памяти, линейной от размера исходного списка (для хранения промежуточных данных во время рекурсивных вызовов алгоритма для нахождения медианы).

Date: 2004-07-11 07:52 pm (UTC)
From: [personal profile] alll
Еще уточнение, если не затруднит: для элементов списка существуют операции "больше"/"меньше"? или только "равно"?

Date: 2004-07-11 08:02 pm (UTC)
From: [identity profile] dyak.livejournal.com
Для четного количества в списке.
Если разделить список на пары, то если член "х" –– большинство, то, если искомый член "х" есть, то, если пары, где члены разные, повыкидывать, то
число пар, где оба члена –– "х" должно быть больше, чем число пар, где оба члена –– "не х". Как предельный случай можно поиграть со списком их а+1 белых и а–1 черных.

Значит действуем так: игнорируем все смешанные пары и ставим счетчик на 0. Идем до первой одинаковой пары, замечаем ее члены как кандидата на большинство, ставим счетчик на 1. Если следующая одинаковая пара такая же, то увеличиваем счетчик на 1, если она другая, вычитаем из счетчика 1. Если счетчик оказывается на 0, то следующая одинаковая пара дает нам кандидата и 1 в счетчике.

В процессе узнаем сколько членов в списке.

Если в конце процесса имеем не 0 в счетчике и кандидата, то на следующем прогоне считаем сколько найдем кандидата в списке. Если >50%, ура.

На нечетное число членов тривиально распространимо, но писать лень.

Date: 2004-07-11 08:20 pm (UTC)
From: [personal profile] alll
А сколько потребуется "прогонов" в самом худшем случае?

Date: 2004-07-11 08:23 pm (UTC)
From: [identity profile] dyak.livejournal.com
Если счетчик = 0, то большинства нет. Один прогон.

Если счетчик > 0, то два.
Первый для определения кандидата и числа членов в списке.
Второй для проверки, в большинстве ли кандидат.

Date: 2004-07-11 08:25 pm (UTC)
From: [personal profile] alll
Это лучшие случаи. Если кандидат не в большинстве, что будем делать?

Date: 2004-07-11 08:30 pm (UTC)
From: [identity profile] dyak.livejournal.com
Значит нет никого в большинстве.

Date: 2004-07-11 08:35 pm (UTC)
From: [identity profile] avva.livejournal.com
Можно делать больше/меньше при желании.

Date: 2004-07-11 08:42 pm (UTC)
From: [personal profile] alll
Тогда зачем второй прогон?

Date: 2004-07-11 08:43 pm (UTC)
From: [personal profile] alll
1,2,3,1,2,1 - что скажет алгоритм?

Date: 2004-07-11 08:44 pm (UTC)
From: [identity profile] dmitryle.livejournal.com
Кажется, правильно, но зачем пары? Берём первый элемент, объявляем кандидатом, ставим счётчик на 1, и проверяем дальше по одному вашим методом: если равен кандидату, увеличиваем счётчик на один, если не равен - уменьшаем; если счётчик равен нулю, начинаем заново со следуюшего элемента.

Date: 2004-07-11 08:49 pm (UTC)
From: [identity profile] dyak.livejournal.com
Чтоб узнать в большинстве ли кандидат.

Date: 2004-07-11 08:50 pm (UTC)
From: [identity profile] dyak.livejournal.com
0, 0, 0
Нет никого больше половины.
Page 1 of 4 << [1] [2] [3] [4] >>

December 2025

S M T W T F S
  123 4 56
78 9 10 11 1213
1415 1617181920
21 22 23 24 2526 27
2829 30 31   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 2nd, 2026 10:28 am
Powered by Dreamwidth Studios