Сортировка чисел по алгоритму суммы

У меня вопрос об алгоритме, не зависящий от языка.

Это происходит из-за (вероятно, простой) задачи программирования, которую я прочитал. Проблема в том, что я слишком глуп, чтобы понять это, и достаточно любопытен, что меня это беспокоит.

Цель состоит в том, чтобы отсортировать список целых чисел в порядке возрастания, поменяв местами числа в списке. Каждый раз, когда вы меняете местами два числа, вы должны добавить их сумму к промежуточной сумме. Задача состоит в том, чтобы создать отсортированный список с наименьшей возможной промежуточной суммой. Примеры:

3 2 1 - 4
1 8 9 7 6 - 41
8 4 5 3 2 7 - 34

Хотя вы можете просто дать ответ, если хотите, но если вы предпочитаете «подсказку» в правильном направлении (если такое возможно), я бы предпочел это.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
1 792
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Как намек, это пахнет динамическим программированием; Возможно, это недостаточно точный намек, чтобы помочь, но я бы предпочел начать с малого!

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

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

Очевидно, что минимизация общих свопов важна. Также важно минимизировать свопы больших чисел.

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

Я предполагаю, что память свободна, и вы можете смоделировать сортировку, прежде чем выполнять ее на реальных объектах.

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

Запустите цикл, который удаляет элемент очереди с наименьшей стоимостью и ставит в очередь все возможные шаги однократной замены, начиная с этой точки. Продолжайте запускать цикл, пока в заголовке очереди не появится отсортированный список.

Я думаю, что у этой проблемы нет тривиального решения, и мой подход, вероятно, не лучше, чем подход с приоритетной очередью.

Найдите наименьшее число N. Любые пары чисел, которые занимают желаемые места друг друга, должны быть заменены местами, кроме N. Соберите (грубой силой) коллекцию каждого набора чисел, которые можно взаимно поменять местами в нужные места, так, чтобы стоимость сортировки набора между собой была меньше, чем стоимость замены каждого элемента набора на N. Эти наборы будут состоять из нескольких циклов. Меняйте местами эти циклы таким образом, чтобы наименьшее число менялось местами дважды. Поменяйте местами все оставшиеся числа, которые составляют цикл, включающий N, используя N в качестве заполнителя.

Уже есть принятое решение, которое является более или менее правильным ответом - вы можете доказывать, что (с очевидной модификацией) оно оптимально. «Свести» что-то к NP-сложной задаче слишком просто; это ничего не говорит о сложности исходной задачи: P

ShreevatsaR 20.11.2008 05:56

Почему вы сказали «уже», если я отправил свой за час до принятого ответа? Игнорируя на мгновение, что принятый ответ неверен.

Sparr 19.12.2008 01:10

Уже есть один контрпример вашей гипотезе. См. Анализ Раймонда.

recursive 29.12.2008 02:32

К чьей гипотезе (к сожалению, "ваша" двусмысленно в плоском списке комментариев)? Анализ Раймонда подтверждает мой ответ и мое возражение против принятого решения и комментария Шриватсы.

Sparr 29.12.2008 23:19

Я сделал несколько попыток решить один из примеров вручную:

  • 1 8 9 7 6
  • 6 8 9 7 1 (+ 6 + 1 = 7)
  • 6 8 1 7 9 (7 + 1 + 9 = 17)
  • 6 8 7 1 9 (17 + 1 + 7 = 25)
  • 6 1 7 8 9 (25 + 1 + 8 = 34)
  • 1 6 7 8 9 (34 + 1 + 6 = 41)

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

Если проблема допускает «закрытые» ответы, вы можете просто создать жадный алгоритм, который помещает самый большой элемент в позицию - либо делая это напрямую, либо сначала меняя местами самый маленький элемент в этот слот.

Ответ принят как подходящий

Прочтите только первые два абзаца, вам просто нужна подсказка. Есть эффективное решение (если, конечно, я не ошибся). Сначала отсортируйте список. Теперь мы можем записать исходный список как список произведений непересекающихся циклов.

Например, 5,3,4,2,1 имеет два цикла: (5,1) и (3,4,2). Цикл можно представить как начало с 3, 4 находится в точке 3, 2 - в точке 4, а 4 - в точке 3. определять. Конечная цель - 1,2,3,4,5 или (1) (2) (3) (4) (5), пять непересекающихся циклов.

Если мы переключим два элемента из разных циклов, скажем 1 и 3, мы получим: 5,1,4,2,3 и в обозначении цикла (1,5,3,4,2). Два цикла объединены в один цикл, это противоположно тому, что мы хотим сделать.

Если мы переключим два элемента из одного цикла, скажем 3 и 4, мы получим: 5,4,3,2,1 в обозначении цикла (5,1) (2,4) (3). Один цикл делится на два меньших цикла. Это приближает нас к цели всех циклов длины 1. Обратите внимание, что любое переключение двух элементов в одном цикле разбивает цикл на два цикла.

Если мы сможем выяснить оптимальный алгоритм переключения одного цикла, мы сможем применить его ко всем циклам и получить оптимальный алгоритм для всей сортировки. Один из алгоритмов состоит в том, чтобы взять минимальный элемент в цикле и переключить его на то, в чьей позиции он находится. Итак, для (3,4,2) мы бы переключили 2 на 4. Это оставляет нам цикл длиной 1 ( элемент только что переключился в правильное положение) и цикл размером на единицу меньше, чем раньше. Затем мы можем снова применить правило. Этот алгоритм переключает наименьшую длину цикла элемента -1 раз и каждый другой элемент один раз.

Чтобы преобразовать цикл длины n в циклы длины 1, требуется n - 1 операция. С каждым элементом нужно работать хотя бы один раз (подумайте о каждом элементе, который нужно отсортировать, он должен быть перемещен в правильное положение). Предложенный мной алгоритм воздействует на каждый элемент один раз, что должны делать все алгоритмы, затем все остальные операции выполняются с минимальным элементом. Нет алгоритма лучше.

Этот алгоритм занимает O (n log n) для сортировки, а затем O (n), чтобы возиться с циклами. Решение одного цикла занимает O (длина цикла), общая длина всех циклов равна n, поэтому стоимость операций цикла составляет O (n). Конечное время выполнения - O (n log n).

У вас есть правильная идея, но вы упустили одну хитрость. (Не публиковать это как ответ, потому что исходный постер хотел только намек.) Вот подсказка для ты - посмотрите, как отсортировать (1 8 9 7 6) с ценой всего 41, а не 42 :-) [Подсказка: у вас есть использовать 1, даже если он находится в нужном месте.]

ShreevatsaR 19.11.2008 09:19

Случай 18976 демонстрирует исключение, описанное в моем решении, поскольку в некоторых случаях достаточно маленькое «временное» число более эффективно для замены других чисел по отдельности, чем использование одного дополнительного числа из цикла дважды.

Sparr 20.11.2008 04:55

Также не работает для 8 4 5 3 2 7 или даже 3 1 2. Этот ответ минимизирует количество свопов, но не суммы.

xan 06.03.2011 22:12

Другие вопросы по теме