Решение для начинающих на Python для CSES «Перестановки»

Я работаю над набором задач CSES, когда учусь программировать, и это решение было принято, но меня оно не совсем устраивало. Я просто знаю, что есть более быстрый способ проверить, действительно ли решение, вместо того, чтобы перебирать каждый элемент, и я уверен, что можно было бы внести еще много улучшений. Любые отзывы приветствуются!

Проблема: Перестановка целых чисел 1, 2,…, n называется красивой, если нет смежных элементов, разность которых равна 1. Для данного n построить красивую перестановку, если такая перестановка существует. Если решений несколько, вы можете распечатать любое из них. Если решений нет, выведите «NO SOLUTION».

def check_solution(sol):
    last = sol[0]
    for num in sol:
        if num - last == 1 or num - last == -1:
            return False
        last = num
    return True


a = [int(x) for x in range(1, int(input())+1)]
b = []
even = a[1::2]
odd = a[::2]

b.extend(even)
b.extend(odd)

if check_solution(b):
    print(*b)
else:
    print("NO SOLUTION")

1 ответ
1

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

def beautiful_permutation(n):
    odd  = list(range(1, n + 1, 2))
    even = list(range(2, n + 1, 2))
    return even + odd

Вашему валидатору, вероятно, следует проверить больше вещей, и его также можно упростить, воспользовавшись преимуществами abs(). При желании вы можете выразить проверку соседнего числа, используя all() и zip(). Мы все еще перебираем числа, но только более кратко.

def check_solution(n, sol):
    return (
        # Must not be empty.
        sol and
        # Must cover all intergers 1 through N.
        set(range(1, n + 1)) == set(sol) and
        # No adjacent numbers with difference of 1.
        all(abs(a - b) != 1 for a, b in zip(sol, sol[1:]))
    )

Еще один момент. Метод, используемый для создания последовательности, почти гарантирует достоверность. По определению, отдельные подсписки (odd и even) будет следовать правилу смежных чисел. Проблема может возникнуть только в месте соединения, где мы их склеиваем. Но наша функция может напрямую проверить проблему. Если вы добавите это и включите предварительную проверку на наличие неправильных или специальных входов (0, 1и т. д.), у вас будет функция, которая, по крайней мере, с практической точки зрения, доказуемо верна — валидатор не нужен!?!

if odd and even and abs(even[-1] - odd[0]) != 1:
    return even + odd
else:
    return None

  • Я думаю, что ваше «доказуемо правильное» решение неверно для n = 1.

    — Келли Банди

  • @KellyBundy Похоже на дефиниционный случай. В любом случае OP может с этим разобраться.

    — FMc

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

    — Тайлер

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *