Подтвердить что ты не робот

Продуманная правильная перестановка менее чем O (n ^ 2)

Написанный в Haskell, вот тип данных, который доказывает, что один список является перестановкой другой:

data Belongs (x :: k) (ys :: [k]) (zs :: [k]) where
  BelongsHere :: Belongs x xs (x ': xs)
  BelongsThere :: Belongs x xs xys -> Belongs x (y ': xs) (y ': xys)

data Permutation (xs :: [k]) (ys :: [k]) where
  PermutationEmpty :: Permutation '[] '[]
  PermutationCons :: Belongs x ys xys -> Permutation xs ys -> Permutation (x ': xs) xys

С помощью Permutation мы можем переписать запись:

data Rec :: (u -> *) -> [u] -> * where
  RNil :: Rec f '[]
  (:&) :: !(f r) -> !(Rec f rs) -> Rec f (r ': rs)

insertRecord :: Belongs x ys zs -> f x -> Rec f ys -> Rec f zs
insertRecord BelongsHere v rs = v :& rs
insertRecord (BelongsThere b) v (r :& rs) = r :& insertRecord b v rs

permute :: Permutation xs ys -> Rec f xs -> Rec f ys
permute PermutationEmpty RNil = RNil
permute (PermutationCons b pnext) (r :& rs) = insertRecord b r (permute pnext rs)

Это прекрасно работает. Тем не менее, permute O(n^2), где n - длина записи. Мне интересно, есть ли способ сделать это быстрее, используя другой тип данных для представления перестановки.

Для сравнения, в изменяемой и нетипизированной настройке (которая, как мне известно, действительно отличается от очень), мы могли бы применить перестановку к гетерогенной записи, подобной этой, в O(n) времени. Вы представляете запись как массив значений и перестановку в виде массива новых позиций (дубликаты не допускаются, а все цифры должны быть между 0 и n). Применение перестановки - это просто повторение этого массива и индексация в массив записей с этими позициями.

Я не ожидаю, что перестановка O(n) возможна в более строго типизированных настройках. Но похоже, что O(n*log(n)) возможно. Я ценю любую обратную связь, и дайте мне знать, если мне нужно что-то разъяснить. Кроме того, ответы на это могут использовать Haskell, Agda или Idris в зависимости от того, с чем легче общаться.

4b9b3361

Ответ 1

Более простым простым решением является сравнение упорядоченной перестановки перестановок.

  • Данные перестановки A и B.

  • Тогда существуют отсортированные перестановки,

    As = sort (A) Bs = sort (B)

  • Как и перестановка A и Bs является перестановкой B.

  • Если As == Bs, то A является перестановкой B.

Таким образом, порядок этого алгоритма равен O (n log (n)) < O (N²)

И это приводит к оптимальному решению.

Использование другого хранилища перестановок дает O (n)

Используя приведенные выше инструкции, мы меняем формат хранения каждой перестановки на

  • отсортированные данные
  • исходные несортированные данные

Чтобы определить, является ли список перестановкой другой, простое сравнение отсортированных данных необходимо → O (n).

Это правильно отвечает на вопрос, но усилия скрыты при создании дублированного хранилища данных ^^ Так что это будет зависеть от использования, если это реальное преимущество или нет.