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)
ifi=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;
}
// ************************************************************************
}
}