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
Arrays 查找给定数组排列的(词典)索引。_Arrays_Algorithm_Permutation - Fatal编程技术网

Arrays 查找给定数组排列的(词典)索引。

Arrays 查找给定数组排列的(词典)索引。,arrays,algorithm,permutation,Arrays,Algorithm,Permutation,给定一个数组,比如说“bca”,我需要找到在字典上大于给定排列的排列数 因此,在此示例中,cab、cba是更大的排列。因此答案是2 我试图通过查找数组的词典排序来解决这个问题,但无法设计一个有效的算法来解决这个问题 任何正确方向的帮助/指示都将不胜感激 基于阶乘数系统和莱默码,有一种非常干净的方法可以做到这一点。其思想是为每个可能的排列分配一个数字代码,对值出现的顺序进行编码。然后,可以将Lehmer代码转换为一个数字,该数字确定所有置换列表中置换的索引(这将使用)。给定排列的索引,然后可以计算

给定一个数组,比如说“bca”,我需要找到在字典上大于给定排列的排列数

因此,在此示例中,cab、cba是更大的排列。因此答案是2

我试图通过查找数组的词典排序来解决这个问题,但无法设计一个有效的算法来解决这个问题


任何正确方向的帮助/指示都将不胜感激

基于阶乘数系统和莱默码,有一种非常干净的方法可以做到这一点。其思想是为每个可能的排列分配一个数字代码,对值出现的顺序进行编码。然后,可以将Lehmer代码转换为一个数字,该数字确定所有置换列表中置换的索引(这将使用)。给定排列的索引,然后可以计算(n!-1)并减去索引以确定还有多少个排列

如果你想知道如何做到这一点,我有一个可以让你从排列映射到索引,反之亦然。我也给了一个,;详情见幻灯片的后半部分


希望这有帮助

让我们看看排列
dacb
。在这四种语言中,这是从哪里来的24个排列的
abcd

  • 考虑第一个字母
    d
    。在剩余的字母(
    acb
    )中,有三个字母比
    d
    小,三个!=6个排列,从每个排列开始,总共18个排列
  • 考虑前两个字母
    da
    。在剩余的字母(
    cb
    )中,没有小于
    a
    的字母(如果有,将有2!=2个以
    d
    开头的排列加上每个排列),总共0个排列
  • 考虑前三个字母
    dac
    。在剩余的字母(
    b
    )中,有一个比
    c
    小,还有一个!=1个以
    dab
    开头的排列,总共1个排列
因此,总共有19个排列小于
dacb
。让我们检查一下

来自itertools导入置换的
>
>>>列表(枚举(“”.join(p)表示排列中的p('abcd'))
[(0,'abcd'),(1,'abdc'),(2,'acbd'),(3,'acdb'),
(4,“adbc”),(5,“adcb”),(6,“bacd”),(7,“badc”),
(8,'bcad'),(9,'bcda'),(10,'bdac'),(11,'bdca'),
(12,“cabd”),(13,“cadb”),(14,“cbad”),(15,“cbda”),
(16,“cdab”),(17,“cdba”),(18,“dabc”),(19,“dacb”),
(20,'dbac')、(21,'dbca')、(22,'dcab')、(23,'dcba')]
看起来不错。所以有4个!− 19− 1=4个大于
dacb
的排列

现在应该清楚如何推广该方法以生成算法。下面是Python的一个实现:

从数学导入阶乘
def字典索引(p):
"""
返回所有元素中排列'p'的词典索引
其元素的排列。`p`必须是序列和所有元素
“p”的值必须是不同的。
>>>词典索引(dacb)
19
>>>从itertools导入置换
>>>全部(词典索引(p)=i
…对于枚举中的i,p(置换('abcde'))
真的
"""
结果=0
对于范围内的j(len(p)):
k=总和(如果i
以下是回溯解决方案:

程序将对给定字符串的所有解决方案进行排列,并返回一个解决方案列表以及其中的解决方案数量

例: 对于
acb
它返回:

c a b
c b a
b a c
b c a
4
代码:

#包括
#包括
使用名称空间std;
int v[100],n,cnt;
char*str;
void init(int k)
{
v[k]=-1;
}
布尔解到达(整数k)
{
如果(k==n+1)
返回true;
返回false;
}
无效打印解决方案(int k)
{
对于(int i=1;i0)
{
返回true;
}
其他的
返回false;
}
返回true;
}
无效bkt(int k)
{
如果(达到溶液(k))
打印液(k);
其他的
{
init(k);
while(hasSuccesor(k))
if(isValid(k))
bkt(k+1);
}
}
int main(int argc,char*argv[])
{
str=“bca”;
n=strlen(str);
bkt(1);
printf(“%i\n”,--cnt);
返回0;
}

直截了当的python解决方案依赖于这样一个事实,即Pythons置换生成器将从初始排序的字符串按字典顺序生成

In [68]: from itertools import permutations

In [69]: from math import factorial

In [70]: def lexigreaterperms(perm):
    ...:     return factorial(len(perm)) - 1 -  list(permutations(sorted(perm))).index(tuple(perm))

In [71]: lexigreaterperms('bca')
Out[71]: 2

In [72]: lexigreaterperms('dacb')
Out[72]: 4

你试过回溯法吗?它实际上效率不高,但确实有效。如果您想让我发布一些代码,请告诉我。@kilotaras:不。排列必须使用与通常相同数量的文字组成definition@Thanatos:不,我不知道回溯方法。你能解释一下并张贴一些代码吗?谢谢@保托姆布林-问题本质上是“做X的有效算法是什么?”。没有(伪)代码的人怎么能回答这个问题呢?那么如果你尝试
lexigreaterperms(范围(20))
,会发生什么呢?@Gareth Rees:什么
In [68]: from itertools import permutations

In [69]: from math import factorial

In [70]: def lexigreaterperms(perm):
    ...:     return factorial(len(perm)) - 1 -  list(permutations(sorted(perm))).index(tuple(perm))

In [71]: lexigreaterperms('bca')
Out[71]: 2

In [72]: lexigreaterperms('dacb')
Out[72]: 4