我知道,对于k
- p
大小k
,根据n
元素构建,有以下内容:
P(n, k) = n! / (n - k)!
可能k
- 排列。例如:
k = 2
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 2)! = 12
1 2 | 2 1 | 3 1 | 4 1
1 3 | 2 3 | 3 2 | 4 2
1 4 | 2 4 | 3 4 | 4 3
又一个例子:
k = 3
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 3)! = 24
1 2 3 | 2 1 3 | 3 1 2 | 4 1 2
1 2 4 | 2 1 4 | 3 1 4 | 4 1 3
1 3 2 | 2 3 1 | 3 2 1 | 4 2 1
1 3 4 | 2 3 4 | 3 2 4 | 4 2 3
1 4 2 | 2 4 1 | 3 4 1 | 4 3 1
1 4 3 | 2 4 3 | 3 4 2 | 4 3 2
那么,我如何找到k
- 排列p
的索引?考虑排列
按字典顺序生成。
修改:
我可以先找到" block" p
是p
的第一个元素处理块。例如,对于p = [3, 2, 4]
,p
的索引应至少为12(从0到P(n, k) - 1
)。
但是,为了找到第二个元素"阻止",我必须看到剩下的项目是什么,以及它们将处于什么位置。我的意思是,我最终会在列表[1, 4]
中找到,而4会在第2位,所以简单地使用元素作为键需要一些额外的操作。
我可以使用哈希来查找元素并更新其位置,但它会给我O(n^2)
时间复杂度。有可能做得更好吗?
答案 0 :(得分:3)
给定位置中给定数字的排列数由公式给出 (n位数位置)! /(n-k)!数字位置从左侧开始,为1。
要获得给定排列的先前排列数(即其索引),请将每个数字的公式乘以尚未使用的先前数字的数字,然后将它们相加。
实施例1,k = 2,n = 4,p = [3,4]
第一个数字,3: (4-1)! /(4-2)! *(未使用的前面的数字,2)= 6 在第一个之前有六个排列,在位置1中有3个。
第二个数字,4: (4-2)! /(4-2)! *(未使用的前面的数字,2)= 2 在第一个之前有两个排列,在位置2中有4个。
零基指数:6 + 2 = 8.
实施例2,k = 3,n = 4,p = [3,2,4]
第一个数字,3: (4-1)! /(4-3)! *(未使用的前面的数字,2)= 12 在第一个之前有12个排列,在位置1中有3个。
第二位,2: (4-2)! /(4-3)! *(未使用的前面位数,1)= 2 在第一个之前有两个排列,在位置2中有2个。
第三位,4: (4-3)! /(4-3)! *(未使用的前一位数,1)= 1 在第一个之前有一个排列,在第3个位置有4个。
零基指数:12 + 2 + 1 = 15.
答案 1 :(得分:1)
使用binary search tree(BST)。在开始之前将所有数字存储在其中,并在使用之后将其删除。要找到每个顶点的第x个元素维护.subtreeSize
,只需下降树以找到所需的数字。伪代码:
def findXth(x):
curVertex = BST.root
while:
curPosition = curVertex.leftChild.subtreeSize
if curPosition == x: return curVertex.value
elif curPosition > x: curVertex = curVertex.leftChild
elif curPosition < x: curVertex = curVertex.rightChild
不要忘记检查顶点的存在并删除找到的顶点。
整体复杂性将为O(n log n)。
答案 2 :(得分:0)
你可以参考下面的功能
/**
* list all k or <=k size permutation of a given list with n unique elements.
* n can be bigger than 64. this function will take O(K^N) time, Bad.
*
* @param uniqueList
* @param permutationSize
* @param permutation
* @param only Only show the permutation of permutationSize,
* else show all permutation of less than or equal to permutationSize.
*/
public static void my_permutationOf(List<Integer> uniqueList, int permutationSize, List<Integer> permutation, boolean only) {
if (permutation == null) {
assert 0 < permutationSize && permutationSize <= uniqueList.size();
permutation = new ArrayList<>(permutationSize);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
}
}
for (int i : uniqueList) {
if (permutation.contains(i)) {
continue;
}
permutation.add(i);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
} else if (permutation.size() == permutationSize) {
System.out.println(Arrays.toString(permutation.toArray()));
}
if (permutation.size() < permutationSize) {
my_permutationOf(uniqueList, permutationSize, permutation, only);
}
permutation.remove(permutation.size() - 1);
}
}
E.g。你可以认为元素是索引
public static void main(String[] args) throws Exception {
my_permutationOf(new ArrayList<Integer>() {
{
add(0);
add(1);
add(2);
add(3);
}
}, 3, null, true);
}
结果是
[0, 1, 2]
[0, 1, 3]
[0, 2, 1]
[0, 2, 3]
[0, 3, 1]
[0, 3, 2]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]