如果一个数组说“bca”,我需要找到排列数量大于给定排列的排列数。
因此,在这个例子中,cab,cba是更大的排列。因此答案是2。
我尝试通过查找数组的词典排名来解决问题,但我无法为说法设计一个有效的算法。
赞赏任何正确方向的帮助/指示!
答案 0 :(得分:16)
让我们看一下排列dacb
。 4这里的字典顺序在哪里出现! = abcd
的24个排列?
d
。在剩余的字母(acb
)中,有三个字母小于d
和3! = 6个排列从每个排列开始,总共18个排列。da
。在剩余的字母(cb
)中,没有小于a
的字母(如果有任何字母会以d
加上每一个而有2!= 2个排列),总共0排列。dac
。在剩余的字母(b
)中,有一个小于c
的字母和1! = 1以dab
开头的排列,总共1个排列。总共有19个排列小于dacb
。我们来检查一下。
>>> from itertools import permutations
>>> list(enumerate(''.join(p) for p in permutations('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中的一个实现:
from math import factorial
def lexicographic_index(p):
"""
Return the lexicographic index of the permutation `p` among all
permutations of its elements. `p` must be a sequence and all elements
of `p` must be distinct.
>>> lexicographic_index('dacb')
19
>>> from itertools import permutations
>>> all(lexicographic_index(p) == i
... for i, p in enumerate(permutations('abcde')))
True
"""
result = 0
for j in range(len(p)):
k = sum(1 for i in p[j + 1:] if i < p[j])
result += k * factorial(len(p) - j - 1)
return result
def lexicographic_followers(p):
"""
Return the number of permutations of `p` that are greater than `p`
in lexicographic order. `p` must be a sequence and all elements
of `p` must be distinct.
"""
return factorial(len(p)) - lexicographic_index(p) - 1
答案 1 :(得分:13)
基于阶乘数系统和Lehmer代码,有一种非常简洁的方法可以做到这一点。我们的想法是为每个可能的排列分配一个数字代码,该排列对值的出现顺序进行编码(Lehmer code)。然后,您可以将Lehmer代码转换为一个数字,该数字确定所有排列列表中的排列索引(这使用factorial number system)。给定置换的索引,然后你可以计算(n! - 1)并减去索引以确定有多少排列。
如果您对如何执行此操作感到好奇,我会an implementation of this algorithm让您从排列映射到索引,反之亦然。我也给了talk on how to do this;细节在幻灯片的后半部分。
希望这有帮助!
答案 2 :(得分:0)
这是Backtracking解决方案:
该程序会置换给定字符串的所有解决方案,并返回一个解决方案列表以及这些解决方案的数量。
例:
对于acb
,它返回:
c a b
c b a
b a c
b c a
4
代码:
#include <iostream>
#include <stdio>
using namespace std;
int v[100], n, cnt;
char *str;
void init(int k)
{
v[k] = -1;
}
bool solutionReached( int k )
{
if (k == n + 1)
return true;
return false;
}
void printSolution( int k )
{
for (int i = 1; i < k; i++)
{
printf("%c ", str[v[i]]);
}
printf("\n");
cnt++;
}
bool hasSuccesor( int k )
{
if(v[k] < n - 1)
{
v[k]++;
return true;
}
return false;
}
bool isValid( int k )
{
for (int i = 1; i < k; i++)
{
if (v[i] == v[k])
{
return false;
}
}
if (k == n)
{
char *cuv = (char *) malloc(n * sizeof(char));
for (i = 0; i < n; i++)
cuv[i] = str[v[i + 1]];
if (strcmp(cuv, str) > 0)
{
return true;
}
else
return false;
}
return true;
}
void bkt(int k)
{
if(solutionReached(k))
printSolution(k);
else
{
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);
return 0;
}
答案 3 :(得分:-3)
直接向前的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