迭代矩阵没有嵌套循环

时间:2014-02-22 01:45:21

标签: loops math matrix combinatorics

我想在不使用嵌套循环的情况下迭代大小为n的方阵的主对角线上方的条目。

例如,如果矩阵M的大小为n = 3,则在对角线上方选择(3,2)= 3个条目。其中choose是二项式系数。

for(i=1 to choose(n,2))
  row = getRow(i)
  col = getCol(i)
  M[row,col] = some value

我无法根据索引i提出获取行和列的公式。

例如:

表示size = 3的矩阵,索引从1开始,

i = 1对应于行= 1且col = 2

i = 2对应于行= 1且col = 3

i = 3对应于行= 2且col = 3

3 个答案:

答案 0 :(得分:1)

您可以使用MATLAB的triu命令,如下所示:

n=5; %user input

mat=magic(n);
nRows=size(mat,1);
nCols=size(mat,2);  

%extract the elements above the main diagonal  
u=triu(mat).*(~eye(n));
uT=u.'; %transpose to get the indices in the order you mentioned

%arrange it in a vector
u_ind=uT(uT~=0);

u_ind将包含所需格式的上三角形上方的元素,即u_ind(3)将包含row = 1和col = 4的元素。

要获取这些行和列索引,您可以按如下方式获取它们:

%You can easily get this if you make simple observations. For a matrix of size 5x5
%the number of total elements above main diagonal are: (4+3+2+1)
%i.e. sum of first n-1 elements -> hence the formula below
totalIndices=0.5*n*(n-1);

%number of elements per row you get
indicesPerRow=n-1:-1:1

%I observed that there is some relation between its index and its (row,col) subscript.
%If the index is 5 in a 5x5 matrix, then you can imagine that it is the first non-zero 
%element in the second row -> because first row has 4 elements. If the index was 8, 
%similarly, it would have been first non-zero element in the third row in the upper 
%triangular matrix we have formed. This is what I have translated into code below.

ind1=cumsum(indicesPerRow);
ind2=ind1;

%Enter the number whose (row,col) index you want to find.
myInd=9;
ind2(ind1<myInd)=[];
pos=find(ind1<myInd,1,'last');
ind2=ind2(1);
ind3=rem(ind2,myInd);
detRow=pos+1;
detCol=nCols-ind3;

fprintf('Index %d corresponds to (row,col)=(%d,%d)\n',myInd,detRow,detCol);

答案 1 :(得分:0)

所以想要一个公式!好 !让我们来看一些简单的数学:

第一行的条目数为r*(r+1)/2。因此rowrow*(row+1)/2 <= i的最大整数。因此,row是等式

的正解的整数部分
row*(row+1)/2 = i

重写为

row^2 + row - 2*i = 0

这是一个二次方程式,因此您可以使用平方根来解决它。积极的解决方案是(sqrt(1+8*i) - 1)/2

所以你有:

row(i) = floor((sqrt(1+8*i) - 1)/2)
col(i) = i - row*(row+1)/2

Python演示:

def rc(i):
    r = floor((-1 + sqrt(1+8*i))/2)
    return (r, i-r*(r+1)/2)

测试:

print [rc(i) for i in range(20)]
[(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (3, 3), 
 (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4)]

使用正确的演示文稿

(0, 0), 
(1, 0), (1, 1), 
(2, 0), (2, 1), (2, 2), 
(3, 0), (3, 1), (3, 2), (3, 3), 
(4, 0), (4, 1), (4, 2), (4, 3), (4, 4), 
...

注意:我用0开始我的所有索引。如果你想坚持使用通常的编号,你必须将i,r和c换一。

答案 2 :(得分:-2)

您可以尝试:

n = 3;

for(int i = 1; i <= n; i++) 
{
    for(int j=i+1; j<=n; j++) 
    {
        row = i;
        col = j;
    }
}

结果:
1,2
1,3
2,3