Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在不计算其他置换的情况下求第n个置换_Php_Algorithm_Math_Permutation - Fatal编程技术网

Php 在不计算其他置换的情况下求第n个置换

Php 在不计算其他置换的情况下求第n个置换,php,algorithm,math,permutation,Php,Algorithm,Math,Permutation,给定代表置换原子的N个元素的数组,是否有这样的算法: function getNthPermutation( $atoms, $permutation_index, $size ) 其中,$atoms是元素数组,$permutation\u index是排列的索引,$size是排列的大小 public static String getPermutation(int n, int k) { char temp[] = IntStream.range(1, n + 1).

给定代表置换原子的N个元素的数组,是否有这样的算法:

function getNthPermutation( $atoms, $permutation_index, $size )
其中,
$atoms
是元素数组,
$permutation\u index
是排列的索引,
$size
是排列的大小

    public static String getPermutation(int n, int k) {
        char temp[] = IntStream.range(1, n + 1).mapToObj(i -> "" + i).collect(Collectors.joining()).toCharArray();
        return getPermutationUTIL(temp, k, 0);
    }

    private static String getPermutationUTIL(char temp[], int k, int start) {
        if (k == 1)
            return new String(temp);
        int p = factorial(temp.length - start - 1);
        int q = (int) Math.floor(k / p);
        if (k % p == 0)
            q = q - 1;
        if (p <= k) {
            char a = temp[start + q];
            for (int j = start + q; j > start; j--)
                temp[j] = temp[j - 1];
            temp[start] = a;
        }
        return k - p >= 0 ? getPermutationUTIL(temp, k - (q * p), start + 1) : getPermutationUTIL(temp, k, start + 1);
    }

    private static void swap(char[] arr, int j, int i) {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private static int factorial(int n) {
        return n == 0 ? 1 : (n * factorial(n - 1));
    }
例如:

$atoms = array( 'A', 'B', 'C' );
// getting third permutation of 2 elements
$perm = getNthPermutation( $atoms, 3, 2 );

echo implode( ', ', $perm )."\n";
将打印:

B, A
在$permutation\u索引之前不计算每个置换

我听说了一些关于factoradic置换的事情,但是我发现的每一个实现都会给出一个与V大小相同的置换,这不是我的情况

谢谢。

这取决于你对排列进行“排序”的方式(例如字典顺序)

一种方法是,它给出[0,n!]和所有置换之间的双射

然后对于[0,n!]中的任何数字i,可以计算第i个置换,而不计算其他置换

这种阶乘写入是基于[0到n!]之间的任何数字都可以写入以下事实:

SUM( ai.(i!) for i in range [0,n-1]) where ai <i 

SUM(ai.(i!),对于[0,n-1]范围内的i),其中ai如果您将所有排列存储在内存中,例如存储在数组中,那么您应该能够在O(1)时间内一次将它们取出一个

这意味着您必须存储所有置换,因此,如果计算所有置换需要非常长的时间,或者存储它们需要非常大的空间,那么这可能不是一个解决方案


我的建议是无论如何尝试一下,如果它太大/太慢就回来——如果一个幼稚的解决方案能解决问题,那么找一个“聪明”的解决方案是没有意义的。

正如RickyBobby所说,在考虑排列的字典顺序时,你应该使用阶乘分解

从实践的角度来看,我是这样看的:

  • 执行一种欧几里得除法,除了你用阶乘数,从
    (n-1)开始
    (n-2),等等
  • 将商保持在一个数组中。
    i
    -th商应该是介于
    0
    n-i-1
    之间的数字,其中
    i
    0
    n-1
  • 这个数组是你的排列。问题是,每个商不关心以前的值,因此需要调整它们。更明确地说,您需要将每个值的增量增加到以前的值的相同或更低的次数
下面的C代码应该让您了解它的工作原理(
n
是条目数,
i
是排列的索引):


下面是一个允许选择排列大小的解决方案。例如,除了能够生成10个元素的所有置换外,它还可以生成10个元素之间的成对置换。它还排列任意对象的列表,而不仅仅是整数

函数n_排列($atoms,$index,$size){ 对于($i=0;$i<$size;$i++){ $item=$index%计数($atoms); $index=地板($index/count($atoms)); $result[]=$atoms[$item]; 阵列拼接($atoms,$item,1); } 返回$result; }
用法示例:

($i=0;$i<6;$i++)的
{
print_r(第n个置换(['A','B','C'],$i,2));
}
//=>AB、BA、CA、AC、BC、CB

它是如何工作的?

这背后有一个非常有趣的想法。让我们看一下A、B、C、D的列表。我们可以通过像从一副纸牌中提取元素一样从中提取元素来构造排列。最初我们可以画四个元素中的一个。然后是剩下的三个元素中的一个,依此类推,直到最后我们一无所有

下面是一个可能的选择序列。从顶部开始,我们走第三条路,然后是第一条,第二条,最后是第一条。这就是我们的排列#13

考虑一下,给定这一系列的选择,你将如何通过算法得到数字13。然后反转你的算法,这就是你如何从一个整数重建序列的方法

让我们试着找到一个通用方案,将一系列选择打包成一个没有冗余的整数,然后重新打包

一个有趣的方案叫做十进制数系统。“27”可以被认为是从10中选择路径2,然后从10中选择路径7

但每个数字只能对10个选项进行编码。其他具有固定基数的系统,如二进制和十六进制,也只能对来自固定数量备选方案的选择序列进行编码。我们需要一个基数可变的系统,有点像时间单位,“14:05:29”是小时14从24开始,分钟5从60开始,秒29从60开始

如果我们使用泛型数字到字符串和字符串到数字函数,并愚弄它们使用混合半径,会怎么样?而不是像和那样只取一个基数,而是每个数字取一个基数

功能包(数字、半径){
var n=0;
对于(变量i=0;i=0;i--){
数字。不移位(n%半径[i]);
n=数学楼层(n/半径[i]);
}
返回数字;
}
这行得通吗

//十进制
包装([4,2],[10,10]);//=>42
//二进制
打包([1,0,1,0,1,0],[2,2,2,2,2]);//=>42
//阶乘系统
打包([1,3,0,0,0,0],[5,4,3,2,1]);//=>42
现在回顾一下:

unpack(42[10,10]);//=>[4, 2]
拆包(42[5,4,3,2,1]);//=>[1, 3, 0, 0, 0]
这太美了。现在让我们把这个参数数字系统应用到置换问题上。我们将考虑<代码> a、b、c、d</代码>的长度2排列。总共有多少人?让我们看看:首先我们画4个项目中的一个,然后画剩下的3个项目中的一个,即
4*3=1
9 8 7 6 5 4 3 2 1 0
AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC
from math import factorial

def nthPerm(n,elems):#with n from 0
    if(len(elems) == 1):
        return elems[0]
    sizeGroup = factorial(len(elems)-1)
    q,r = divmod(n,sizeGroup)
    v = elems[q]
    elems.remove(v)
    return v + ", " + ithPerm(r,elems)
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m']

ithPerm(0,letters[:])          #--> a, b, c, d, e, f, g, h, i, j, k, l, m
ithPerm(4,letters[:])          #--> a, b, c, d, e, f, g, h, i, j, m, k, l
ithPerm(3587542868,letters[:]) #--> h, f, l, i, c, k, a, e, g, m, d, b, j
Initialize:
n = length(permutation)
r = desired rank
p = identity permutation of n elements [0, 1, ..., n]

unrank(n, r, p)
  if n > 0 then
    swap(p[n-1], p[r mod n])
    unrank(n-1, floor(r/n), p)
  fi
end
Initialize:
p = input permutation
q = inverse input permutation (in linear time, q[p[i]] = i for 0 <= i < n)
n = length(p)

rank(n, p, q)
  if n=1 then return 0 fi
  s = p[n-1]
  swap(p[n-1], p[q[n-1]])
  swap(q[s], q[n-1])
  return s + n * rank(n-1, p, q)
end
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;
        }

        // ************************************************************************
    }
}
    public static String getPermutation(int n, int k) {
        char temp[] = IntStream.range(1, n + 1).mapToObj(i -> "" + i).collect(Collectors.joining()).toCharArray();
        return getPermutationUTIL(temp, k, 0);
    }

    private static String getPermutationUTIL(char temp[], int k, int start) {
        if (k == 1)
            return new String(temp);
        int p = factorial(temp.length - start - 1);
        int q = (int) Math.floor(k / p);
        if (k % p == 0)
            q = q - 1;
        if (p <= k) {
            char a = temp[start + q];
            for (int j = start + q; j > start; j--)
                temp[j] = temp[j - 1];
            temp[start] = a;
        }
        return k - p >= 0 ? getPermutationUTIL(temp, k - (q * p), start + 1) : getPermutationUTIL(temp, k, start + 1);
    }

    private static void swap(char[] arr, int j, int i) {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private static int factorial(int n) {
        return n == 0 ? 1 : (n * factorial(n - 1));
    }