Python 得到一个置换作为O(n)中唯一给定索引的函数

Python 得到一个置换作为O(n)中唯一给定索引的函数,python,algorithm,permutation,Python,Algorithm,Permutation,我希望有一个函数get_permutation,它给定一个列表l和一个索引I,返回一个l的排列,这样所有I大于0小于n的排列都是唯一的(其中n=len(l)) 即get_置换(l,I)!=获得置换(l,j)ifi=j对于所有i,js.t.0更新:可能重复,请参见此处了解算法 如果len(l)较小,您可以预先计算perm_index=permutations(range(len(l))),并将其用作实际数据中的索引列表 此外,如果您有一个来自range(len(l))的排列列表,并且您需要一个用于

我希望有一个函数
get_permutation
,它给定一个列表
l
和一个索引
I
,返回一个
l
的排列,这样所有
I
大于
0
小于
n的排列都是唯一的(其中
n=len(l)

get_置换(l,I)!=获得置换(l,j)
if
i=j
对于所有
i
j
s.t.
0更新:可能重复,请参见此处了解算法

如果
len(l)
较小,您可以预先计算
perm_index=permutations(range(len(l)))
,并将其用作实际数据中的索引列表

此外,如果您有一个来自
range(len(l))
的排列列表,并且您需要一个用于
range(len(l)-1)
的排列列表,您可以执行以下操作:

[x - 1 for x in perm_index[i][1:]]
它利用了一个事实,即在生成排列时排列顺序是有序的。

基于此,这里有一个可能的解决方案。正如@Gassa所指出的,elements.pop在顺序上不是常数,因此解决方案在列表长度上不是线性的。因此,我不会将此标记为可接受的答案。但是,它起作用了

def integerToCode(idx, permSize):                                                                                                                                       
    if (permSize <= 1):                                                                                                                                                 
        return [0]                                                                                                                                                      
    multiplier = math.factorial(permSize-1)                                                                                                                             
    digit =idx / multiplier                                                                                                                                             
    return [digit] +  integerToCode(idx % multiplier, permSize-1)                                                                                                       


def codeToPermutation(elements, code):                                                                                                                                  
    return map(lambda i: elements.pop(i), code)                                                                                                                         

def get_permutation(l, i):                                                                                                                                              
    c = integerToCode(i, len(l))                                                                                                                                        
    return codeToPermutation(list(l), c)
def integerToCode(idx,permSize):

如果(PrimSimult

)如果你不关心哪一个排列得到哪些索引,如果我们考虑任意整数的算术运算是O(1),则O(n)解成为可能。 例如,请参阅温迪·迈尔沃德和弗兰克·罗斯基的论文“”

简言之,有两个想法


(1)考虑生成随机排列(伪代码)的方法:

这个变换是内射的:如果我们给它一个不同的随机整数序列,它保证产生不同的排列。因此,我们用非随机整数替换随机整数:第一个是0,第二个是0或1,…,最后一个可以是从0到n-1的任意整数


(2) 有n!个n阶排列。我们现在要做的是写一个从0到n的整数!-1 in:最后一个数字总是0,前一个数字是0或1,…,第一个数字有n个从0到n-1的可能性。因此,我们将得到一个唯一的序列来为上面的伪代码提供信息

现在,如果我们把我们的数除以1到n的整数为O(1)运算,把数转化为阶乘系是O(n)的这种划分。严格来说,这不是真的:对于大N,n的数目包含O(n log n)二进制数字的阶数,并且除法的成本与数字数成正比。


实际上,对于小的n,O(n^2)或O(n logn)方法来排列或解列排列,以及需要O(2^n)或O(n!)内存来存储一些预计算值的方法,可能比涉及整数除法的O(n)方法快,后者在现代处理器上是一种相对缓慢的操作。
对于足够大的n!以至于n!不适合机器字,则“O(n)if order-n!integer operations is O(1)”参数将停止工作。因此,如果不坚持理论上n是O(n),则对于小n和大n可能都会更好。

此解决方案适用于
O(1)
(运行时复杂性;字典查找的摊销成本):

代码 输出 工作原理 该代码将所有过去的调用存储在字典中。它还存储置换对象。因此,如果请求新的置换,将使用下一个置换

代码使用了

有点太晚了……C#代码应该会给出您期望的结果:

using System;
using System.Collections.Generic;

namespace WpfPermutations
{
    public class PermutationOuelletLexico3<T>
    {
        // ************************************************************************
        private T[] _sortedValues;

        private bool[] _valueUsed;

        public readonly long MaxIndex; // long to support 20! or less 

        // ************************************************************************
        public PermutationOuelletLexico3(T[] sortedValues)
        {
            if (sortedValues.Length <= 0)
            {
                throw new ArgumentException("sortedValues.Lenght should be greater than 0");
            }

            _sortedValues = sortedValues;
            Result = new T[_sortedValues.Length];
            _valueUsed = new bool[_sortedValues.Length];

            MaxIndex = Factorial.GetFactorial(_sortedValues.Length);
        }

        // ************************************************************************
        public T[] Result { get; private set; }

        // ************************************************************************
        /// <summary>
        /// Return the permutation relative to the index received, according to 
        /// _sortedValues.
        /// Sort Index is 0 based and should be less than MaxIndex. Otherwise you get an exception.
        /// </summary>
        /// <param name="sortIndex"></param>
        /// <param name="result">Value is not used as inpu, only as output. Re-use buffer in order to save memory</param>
        /// <returns></returns>
        public void GetValuesForIndex(long sortIndex)
        {
            int size = _sortedValues.Length;

            if (sortIndex < 0)
            {
                throw new ArgumentException("sortIndex should be greater or equal to 0.");
            }

            if (sortIndex >= MaxIndex)
            {
                throw new ArgumentException("sortIndex should be less than factorial(the lenght of items)");
            }

            for (int n = 0; n < _valueUsed.Length; n++)
            {
                _valueUsed[n] = false;
            }

            long factorielLower = MaxIndex;

            for (int index = 0; index < size; index++)
            {
                long factorielBigger = factorielLower;
                factorielLower = Factorial.GetFactorial(size - index - 1);  //  factorielBigger / inverseIndex;

                int resultItemIndex = (int)(sortIndex % factorielBigger / factorielLower);

                int correctedResultItemIndex = 0;
                for(;;)
                {
                    if (! _valueUsed[correctedResultItemIndex])
                    {
                        resultItemIndex--;
                        if (resultItemIndex < 0)
                        {
                            break;
                        }
                    }
                    correctedResultItemIndex++;
                }

                Result[index] = _sortedValues[correctedResultItemIndex];
                _valueUsed[correctedResultItemIndex] = true;
            }
        }

        // ************************************************************************
        /// <summary>
        /// Calc the index, relative to _sortedValues, of the permutation received
        /// as argument. Returned index is 0 based.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetIndexOfValues(T[] values)
        {
            int size = _sortedValues.Length;
            long valuesIndex = 0;

            List<T> valuesLeft = new List<T>(_sortedValues);

            for (int index = 0; index < size; index++)
            {
                long indexFactorial = Factorial.GetFactorial(size - 1 - index);

                T value = values[index];
                int indexCorrected = valuesLeft.IndexOf(value);
                valuesIndex = valuesIndex + (indexCorrected * indexFactorial);
                valuesLeft.Remove(value);
            }
            return valuesIndex;
        }

        // ************************************************************************
    }
}
使用系统;
使用System.Collections.Generic;
命名空间WpfPermutations
{
公共类置换
{
// ************************************************************************
私人T[]_分类值;
使用的私有布尔值【】;
public readonly long MaxIndex;//long支持20!或更少
// ************************************************************************
公共置换ouelletlexico3(T[]分类值)
{
if(sortedValues.Length=MaxIndex)
{
抛出新的ArgumentException(“sortIndex应该小于阶乘(项的长度)”);
}
用于(int n=0;n<_valueUsed.Length;n++)
{
_valueUsed[n]=假;
}
长阶乘低=最大索引;
对于(int index=0;indexp = [0, 1, ..., n-1]
for i := 0 upto n-1:
    j := random_integer (0, i)
    exchange p[i] and p[j]
#!/usr/bin/env python

import itertools


def get_permutation():
    memoize = {}

    def _memoizer(l, i):
        if str(l) in memoize and i not in memoize[str(l)]:
            memoize[str(l)][i] = memoize[str(l)]['permutations'].next()
        else:
            p = itertools.permutations(l)
            memoize[str(l)] = {'permutations': p}
            memoize[str(l)][i] = memoize[str(l)]['permutations'].next()
        return memoize[str(l)][i]
    return _memoizer

if __name__ == '__main__':
    get_permutation = get_permutation()
    l1 = list(range(10))
    l2 = list(range(5))
    print(get_permutation(l1, 1))
    print(get_permutation(l1, 20))
    print(get_permutation(l2, 3))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
(0, 1, 2, 3, 4, 5, 6, 7, 9, 8)
(0, 1, 2, 3, 4)
using System;
using System.Collections.Generic;

namespace WpfPermutations
{
    public class PermutationOuelletLexico3<T>
    {
        // ************************************************************************
        private T[] _sortedValues;

        private bool[] _valueUsed;

        public readonly long MaxIndex; // long to support 20! or less 

        // ************************************************************************
        public PermutationOuelletLexico3(T[] sortedValues)
        {
            if (sortedValues.Length <= 0)
            {
                throw new ArgumentException("sortedValues.Lenght should be greater than 0");
            }

            _sortedValues = sortedValues;
            Result = new T[_sortedValues.Length];
            _valueUsed = new bool[_sortedValues.Length];

            MaxIndex = Factorial.GetFactorial(_sortedValues.Length);
        }

        // ************************************************************************
        public T[] Result { get; private set; }

        // ************************************************************************
        /// <summary>
        /// Return the permutation relative to the index received, according to 
        /// _sortedValues.
        /// Sort Index is 0 based and should be less than MaxIndex. Otherwise you get an exception.
        /// </summary>
        /// <param name="sortIndex"></param>
        /// <param name="result">Value is not used as inpu, only as output. Re-use buffer in order to save memory</param>
        /// <returns></returns>
        public void GetValuesForIndex(long sortIndex)
        {
            int size = _sortedValues.Length;

            if (sortIndex < 0)
            {
                throw new ArgumentException("sortIndex should be greater or equal to 0.");
            }

            if (sortIndex >= MaxIndex)
            {
                throw new ArgumentException("sortIndex should be less than factorial(the lenght of items)");
            }

            for (int n = 0; n < _valueUsed.Length; n++)
            {
                _valueUsed[n] = false;
            }

            long factorielLower = MaxIndex;

            for (int index = 0; index < size; index++)
            {
                long factorielBigger = factorielLower;
                factorielLower = Factorial.GetFactorial(size - index - 1);  //  factorielBigger / inverseIndex;

                int resultItemIndex = (int)(sortIndex % factorielBigger / factorielLower);

                int correctedResultItemIndex = 0;
                for(;;)
                {
                    if (! _valueUsed[correctedResultItemIndex])
                    {
                        resultItemIndex--;
                        if (resultItemIndex < 0)
                        {
                            break;
                        }
                    }
                    correctedResultItemIndex++;
                }

                Result[index] = _sortedValues[correctedResultItemIndex];
                _valueUsed[correctedResultItemIndex] = true;
            }
        }

        // ************************************************************************
        /// <summary>
        /// Calc the index, relative to _sortedValues, of the permutation received
        /// as argument. Returned index is 0 based.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetIndexOfValues(T[] values)
        {
            int size = _sortedValues.Length;
            long valuesIndex = 0;

            List<T> valuesLeft = new List<T>(_sortedValues);

            for (int index = 0; index < size; index++)
            {
                long indexFactorial = Factorial.GetFactorial(size - 1 - index);

                T value = values[index];
                int indexCorrected = valuesLeft.IndexOf(value);
                valuesIndex = valuesIndex + (indexCorrected * indexFactorial);
                valuesLeft.Remove(value);
            }
            return valuesIndex;
        }

        // ************************************************************************
    }
}