Поиск наиболее оптимального способа обновления массива динамического программирования

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

repeat
    swapped = false
    for i from 1 to n do:
        if a[i] > a[i+1] then
            add a friendship between a[i] and a[i+1]
            swap(a[i], a[i+1])
            swapped = true
        end if
    end for
until not swapped

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

3
3 1 2

Пример вывода:

2

Я попытался решить эту проблему, используя этот код:

n = int(input())
permutation = list(map(int, input().split()))
dp = [[] for _ in range(n)]
max_length = 0
for i in range(n):
    dp[i].append(i)
    for j in range(i):
        if permutation[j] < permutation[i]:
            addable = True
            for k in dp[j]:
                if (permutation[k] > permutation[i] and k < i) or (permutation[k] < permutation[i] and k > i):
                    addable = False
                    break
            if addable and len(dp[j]) + 1 > len(dp[i]):
                dp[i] = dp[j].copy()
                dp[i].append(i)
    if len(dp[i]) > max_length:
        max_length = len(dp[i])

print(max_length)

который отлично работает для всех входных данных и дает нам правильный ответ, как я проверил, но имеет временную сложность O(n^3), что совершенно не подходит для больших входных данных. Есть ли способ оптимизировать этот код?! Или хотя бы есть другое решение и подход к этому?! Этот код предполагает, что при каждой замене ребро из полного графа с n вершинами удаляется, и с учетом этого ребра между двумя индексами перестановки будут тогда и только тогда, когда индекс, который выше другого, имеет более высокое значение. .

Что именно означает «максимальное количество людей, которые не являются друзьями»?

no comment 16.05.2024 15:28

Вы словно считаете количество инверсий (то есть пар (x, y) таких, что x < y и a[x] > a[y]). Если это так, то это делается за O(n*log(n)): вы сортируете массив с помощью своего любимого алгоритма, подсчитывая количество инверсий, которые вы отменяете на каждом шаге. См. stackoverflow.com/questions/337664/….

Abstraction 16.05.2024 16:30

Почему ответ 2 для образца ввода? После сортировки осталась только 1 пара людей, которые не стали друзьями.

Unmitigated 16.05.2024 20:49

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

Cary Swoveland 18.05.2024 02:16

@nocomment Итак, чтобы было ясно: два человека становятся друзьями после завершения операции, если и только если они меняются местами в процессе сортировки, при этом, когда мы пытаемся отсортировать их с помощью заданного алгоритма, между некоторыми людьми возникает некоторая дружба. (Чтобы внести ясность, вы можете считать, что у каждого из них есть имя, и их имя с самого начала является их индексом). Для данного примера при выполнении алгоритма 3 и 1 поменяются местами, и они станут друзьями, после чего очередь будет выглядеть так: 1 3 2 после 3 и 2 очередь отсортирована и 1 2 не друзья.

FrOZEn_FurY 26.05.2024 20:16
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
5
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

n = int(input())
permutation = list(map(int, input().split()))
dp = []
for i in range(n):
    low, high = 0, len(dp)
    while low < high:
        mid = (low + high) // 2
        if dp[mid] < permutation[i]:
            low = mid + 1
        else:
            high = mid
    if low == len(dp):
        dp.append(permutation[i])
    else:
        dp[low] = permutation[i]

print(len(dp))

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

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