2012-12-05 29 views
1

我正在尋找索引M使用線性索引選擇N個元組。前一段時間我寫了對M代碼選擇2爲一些對索引功能:智能線性索引有N個項目的元組從1開始:M

function K=pairidx(i, j) 
     if(i>j) 
     swap(i,j); 
     K=j-(i+1) + (i)*(2*M-1)-i*(i-1)/2; 
    end 

我現在需要的是這個到M泛化選擇N.理想情況下,我將有一個可逆函數在那裏我可以轉換從索引K到某個元組(K_1,K_2,...,K_N)。到目前爲止,我一直在做一個暴力方法,其中N = 3我寫了下面的函數,但我希望這不是最好的。

function lookup=tripletable() 
d=nchoosek(M,N); 
idx=1; 
lookup=zeros(d,3); 
for i=1:M 
    for j=i+1:M 
     for k=j+1:M 
      lookup(idx,:)=[i,j,k]; 
      idx=idx+1; 
     end 
    end 
end 
+0

除非我誤解你,你可以使用內置函數並[c = nchoosek(V,K )](http://www.mathworks.com/help/matlab/ref/nchoosek.html),其中v是元素的向量。 – jerad

回答

0

由於Jerad評論,你可以使用nchoosek(v,k)產生組合的完整列表,然後讓你的Matlab的(排序)組合匹配任何行。但是,這將需要生成整個列表,如果M和N變大,這個列表可能相當大。

您可以使用以下代碼按索引獲取組合。它會計算可能的組合數量並檢查您提供的索引是否在該範圍內。它然後反覆推移,以確定所有元素

function combination=getCombinationByIndex(v,K,N) 
M=size(v,2); 
k=K; 
l=0; 
combination=zeros(1,N); 
for i=1:N 
    %determine combination(i) 
    while(true) 
     l=l+1; 
     C=nchoosek(M-l,N-i);   
     if(k>C) 
      k=k-C; 
     else 
      combination(i) = v(l); 
      break; 
     end 
    end 
end 

相反的操作是類似的:只是有點你的組合與去年元素,檢查如果你目前的組合是在這個範圍內。

編輯:如按主題起動機提供並擴大以允許任意的套元件的逆操作:

function k=getIndexByCombination(v,combo) 
M=length(v); 
v=sort(v); 
combo=sort(combo); 
N=length(combo); 
l=0; 
%k is the index 
k=1; 
for i=1:N 
    while(true) 
     l=l+1;  
     if(combo(i)==v(l)) 
      break; 
     else 
      C=nchoosek(M-l,N-i); 
      k=k+C; 
     end 
    end 
end 
+0

我必須承認,我並沒有意識到nchoosek(v,k)的矢量能力,但是你的解決方案是非常優雅的,即使對於大的M也有令人印象深刻的速度。唯一的變化是在評估之前應該去掉l = l + 1語句C ie: 'l = 1 + 1; C = nchoosek(M-1,N-1); ' 謝謝 – jdwhitfield

+0

我會修復你的評論,但我應該從0開始(對於v(1)永遠被選中) – Origin

+1

反向操作,以防其他人訪問此主題: 'function k =組合;組合= 'N =長度(組合);' '= 1;' '%k是索引' 'k = 1; (true)' 'l = 1 + 1;' 'C = nchoosek(M1,Ni);' 'if(combo(i)== 1) 'break;' 'else' 'k = k + C;' '結束' '結束' '結束' – jdwhitfield

相關問題