在重新排序的大矩阵中查找重新排序的向量的索引

时间:2016-10-01 23:04:07

标签: matlab indexing

假设我有一个重新排序的矩阵A,可以在MATLAB中使用A = nchoosek(1:100, 6)得到。因此,A表示从1到100中选择6位数的所有组合。

A已重新排序,A的昏暗非常大(1e9 * 6),因此A是这样的:

 1     2     3     4     5     6
 1     2     3     4     5     7
 1     2     3     4     5     8
 .     .     .     .     .     .
 .     .     .     .     .     .
 94    96    97    98    99   100
 95    96    97    98    99   100

然后,我有另一个重新排序的向量B,它是A的成员。例如B=[5 10 11 40 51 67];

那么,如何使用最快的方式找到B的索引,这意味着利用订购信息?

1 个答案:

答案 0 :(得分:3)

您应该注意如何生成A行。我怀疑文档中没有指定,所以你可能不应该过多地依赖它。我的意思是,这是技术上没有文档记录的行为,它可以随任何版本而改变。

但请注意,每个元素从结束索引开始循环,并且每个组合都被排序。这意味着您需要从头开始,在

B = [5 10 11 40 51 67];

第一个索引是5,这意味着枚举了以4开头的所有元素。有多少人?

nchoosek(100-1,6-1)+nchoosek(100-2,6-1)+nchoosek(100-3,6-1)+nchoosek(100-4,6-1)
% [1 . . . . .]       [2 . . . . .]       [3 . . . . .]       [4 . . . . .]
%    ^ 2:100             ^ 3:100             ^ 4:100             ^ 5:100

因为如果第一个元素是1,我们有99个数字可以选择5,如果第一个数字是2则从98中选择5,等等。

接下来是元素[5 6 7 8 9 10][5 9 97 98 99 100]。同样,如果第二个元素是固定的,这些是完整的组合:

nchoosek(100-6,6-2)+nchoosek(100-7,6-2)+nchoosek(100-8,6-2)+nchoosek(100-9,6-2)
% [5 6 . . . .]       [5 7 . . . .]       [5 8 . . . .]       [5 9 . . . .]
%      ^ 7:100             ^ 8:100             ^ 9:100             ^ 10:100

依此类推,直到你构建了[5 10 11 40 50 .]的所有内容,其中包含nchoosek(100-50,6-5)的最后一个词。然后剩下的就是计算从[5 10 11 40 51 52][5 10 11 40 51 67]的元素,即67-52+1

因此,如果您的索引向量B有n个元素,每个都为b_k调用k=1:n,请将其形式化:

sum_{k=1:n} sum_{b=b_{k-1}+1:b_{k}-1} nchoosek(100-b,n-k)

如果我们将第一个索引的b_0定义为零,则会有效,请注意nchoosek(m,0)==1

所以这是一个应该有用的简单功能。它在同类中并不是最优的,但它确实胜过检查1e9向量相互之间的对比:

function ind = find_chooseind(N,B)
% N is the N in 1:N in nchoosek(1:N,K)
% length(B) == K

% define auxiliary B with a zero prepended to avoid out-of-bounds errors
Blen = length(B);
B = [0; B(:)];

ind = 0;
for k=2:Blen+1 % shifted for that first zero
   for b=B(k-1)+1:B(k)-1
      ind = ind + nchoosek(N-b,Blen-(k-1)); % compensate for k shift
   end
end

% testing reveals an off-by-one error, not to worry
ind = ind+1;

我用一个较小的例子测试了上面的代码:

>> N = 20; K = 4;
>> A20_4 = nchoosek(1:N,K);
>> t = A20_4(randi(nchoosek(N,K)),:);
>> ind = find_chooseind(N,t);
>> A20_4(ind,:)

ans =

     7     8     9    14

>> t

t =

     7     8     9    14