我编写了一个函数,用于计算索引中数组[a,b,c,...]的排列,例如:
0 -> a b c
1 -> a c b
2 -> b a c
3 -> b c a
4 -> c a b
5 -> c b a
通过这个递归函数:
function factorial(n) { return n <= 1 ? 1 : n*factorial(n-1); }
function permutation(ar, n) {
if (ar.length == 1) return [ar[0]];
var x = factorial(ar.length-1); // get first element
return ar.splice(Math.floor(n/x),1).concat( permutation( ar, n % x ) )
}
现在我正在寻找一个取排列索引的函数来得到反转排列的索引,即
index perm reversed reversed index
**0** -> a b c -> c b a -> **5**
**1** -> a c b -> b c a -> **3**
**2** -> b a c -> c a b -> **4**
**3** -> b c a -> a c b -> **1**
**4** -> c a b -> b a c -> **2**
**5** -> c b a -> a b c -> **0**
我可以计算所有排列,计算它们的反向并建立它的索引,但似乎应该有一种数学方法来获得反向排列的索引而不计算它。
答案 0 :(得分:2)
如果你看看你的排列,你会发现它的结构如下:(例如lenght = 3)
首先,你的排列分为3组,每组包含2个!分子 然后将这些子组分为2组,每组1个!之后,子分组不再分开。
事实上,你的排列可以被查找起来&#39;首先说明它在哪个子组,然后说明它在哪个子组... 例如,排列2:&#39; bac&#39;在子组1(从0开始)和子组0中。所以我们可以说2 =(1,0),如3 = 1 *(2!)+ 0 *(1!) 那么4将是(2,0) 现在,如果我们翻转2,那么它(0,1)并添加4,(2,0)就可以得到(2,1) 这适用于所有排列
本质上: (n =排列长度)
将您的索引写为*(n-1)! + b *(n-2)! + ... + z *(1!)(a = floor(index /(n-1)),b = floor((index%(n-1))/(n-2)!),... )
找到一个数字,这样如果你翻转最小的一个并将它们加在一起就得到(n-1,n-2,n-3,...,1)
这可能是一种有效的算法。
答案 1 :(得分:0)
我不知道是否有数学方法来实现这一目标,但你可以通过使用hashmap以更快的方式实现这一目标。
var dict = {};
dict['abc'] = 0;
dict['acb'] = 1;
dict['bac'] = 2;
dict['bca'] = 3;
dict['cab'] = 4;
dict['cba'] = 5;
所以一旦你有了这个,你可以使用上面形成的hashmap反转普通字符串并获得它的索引值。
希望这有帮助!
答案 2 :(得分:0)
我有点太晚了......可以计算一下。您可以按原样使用此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 greater or equal to 0.");
}
if (sortIndex >= MaxIndex)
{
throw new ArgumentException("sortIndex should 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;
}
// ************************************************************************
}
}