![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Pawl |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Уважаемые форумчане,
Долго думал, где разместить данную тему, и таки выбрал эту ветку - по 2-м причинам: - похожий вопрос я задавал в алгоритмах, но там мне не помогли; - код все-таки на java. Итак, моя программа ищет рекурсивно перебором все комбинации чисел в массиве, которые бы составили заданную сумму. И она таки их находит, но ищет ДОЛГО! В массиве из 11 чисел для суммы равной 15, она подбирает значения где-то за 11 секунд. Если я не ошибаюсь, тут имеет место 2^11 = 2048 вариантов подбора, что для 3-х ядер в 2100 МГц каждое вообще не должно быть проблемой! Гляньте, пожалуйста, код, и выскажите свои соображения, можно ли в нем что-нибудь оптимизировать. Оговорюсь сразу, что надо делать именно рекурсивным перебором. Спасибо!
-------------------- В действительности всё совсем не так, как на самом деле |
|||
|
||||
AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Я просто попробовал распечатать сколько раз вызывается метод find.
После 100 000 раз выключил задачу. Смотри в алгоритме - там явно ошибка. |
|||
|
||||
Pawl |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Да, я подсчитал: в программе метод вызывается 96308248 раз! ПОЧЕМУ? ![]() -------------------- В действительности всё совсем не так, как на самом деле |
|||
|
||||
Dummy |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 9 Всего: 19 |
Странно, что алгоритмисты не помогли. Это, вроде, как раз по их части.
Помимо неправильной логики рекурсии (нет, я не знаю, где именно баг ![]()
С заданными значениями справляется за несколько миллисекунд. Конечно, появится проблема переполнения стека при большой размерности входного массива, но это детали. Это сообщение отредактировал(а) Dummy - 28.1.2012, 01:50 |
|||
|
||||
Mirkes |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 586 Регистрация: 18.8.2011 Где: Красноярск Репутация: 7 Всего: 17 |
Прочитав логику программы я не понял, как она соотносится с поставленной задачей. Сначала пара вопросов.
1. Если в массиве есть два числа равных 1 это разные числа? поясню вопрос. Пусть дан массив {1,3,1,2,2,10} нужная сумма 15 вариант 3+2+10 может быть получен двумя способами: 1, 3, 5 элементы и 1, 4, 5 элементы ВНИМАНИЕ вопрос ЭТО разные решения? Вопрос не праздный, ответить на него можно только исходя из прикладного смысла. 2. Не взирая на ответ на первый вопрос стоит второй вопрос. Имеет ли значение порядок появления слагаемых. Пояснение рассмотрим решение 1+1+3+10. Его можно записать по разному (далее перечисляются индексы элементов): 0, 1, 2, 5 1, 0, 2, 5 ... Всего 24 (6!) вариантов. Эти варианты различны с точки зрения прикладной интерпретации? Если ответ на первый вопрос Да а на второй нет, то следует просто иначе строить рекурсию. Во первых параметрами будут Текущая сумма и номер последнего включенного элемента. В самой процедуре проверяются только элементы с номерами БОЛЬШЕ текущего. Если порядок значений в начальном массиве не важен, рекомендую отсортировать его один раз, это позволит существенно сократить перебор. Если речь идет о больших массивах, то можно построить алгоритм частичного подсуммирования, но он потребует дополнительной памяти ![]() Просьба уточните постановку задачи, тогда можно будет обсуждать алгоритмы. -------------------- Mirkes |
|||
|
||||
Pawl |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Действительно, Ваш вариант намного быстрее, только в нем встречаются повторяющиеся комбинации. Постоянная сортировка у меня как раз и сделана для того, чтобы списки с одинаковыми элементами не попадали в результат. Mirkes, спасибо за вопросы, отвечаю по порядку: 1)
2)
Там вообще какая-то вялотекущая ветка - за неделю было менее 30 просмотров и только 1 ответ, правда, толковый - мне посоветовали как-то "помечать" элементы исходного массива, чтобы не использовать их повторно. Как помечать, я не додумался и решил просто их удалять. -------------------- В действительности всё совсем не так, как на самом деле |
||||
|
|||||
Dummy |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 9 Всего: 19 |
В соответствии с уточненными условиями и рекомендациями Mirkes уточняем алгоритм:
Это сообщение отредактировал(а) Dummy - 28.1.2012, 10:59 |
|||
|
||||
Pawl |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Что же, спасибо всем за решение моей проблемы! Предложенный Dummy вариант т.ч.н. (то что надо). Ну и буду думать, что не так с моим алгоритмом! А пока тему закрываю.
-------------------- В действительности всё совсем не так, как на самом деле |
|||
|
||||
Pawl |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Согласно Вашим рекомендациям и примеру оптимизировал также свой код:
даже малость покороче получилось ![]() Вопрос к Dummy: почему Вы использовали ArrayList? Я читал, что
И, на мой взгляд тут больше подходит LinkedList, т. к. в данном случае в accum мы постоянно добавляем и удаляем элементы. -------------------- В действительности всё совсем не так, как на самом деле |
||||
|
|||||
Dummy |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 263 Регистрация: 21.5.2007 Репутация: 9 Всего: 19 |
На самом деле, машинально написал - никакого особого смысла не подразумевал ![]() |
|||
|
||||
Pawl |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 649 Регистрация: 22.4.2008 Где: Витебск Репутация: 7 Всего: 28 |
Спасибо, Dummy, еще раз!
![]() ![]() -------------------- В действительности всё совсем не так, как на самом деле |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |