【问题标题】:iterate matrix without nested loop在没有嵌套循环的情况下迭代矩阵
【发布时间】:2014-02-22 01:45:20
【问题描述】:

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

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

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

我还没有想出一个基于索引 i 获取行和列的公式。

例如:

对于大小为 3 且索引从 1 开始的矩阵,

i=1 对应 row = 1 和 col = 2

i=2 对应 row = 1 和 col = 3

i=3 对应 row = 2 和 col = 3

【问题讨论】:

  • 出于什么原因要避免嵌套循环?
  • @pkacprzak 因为我想并行执行它以便简化事情,我也很好奇
  • @Enrique 看到我的回答。

标签: loops math matrix combinatorics


【解决方案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);

【讨论】:

  • 非常感谢。它奏效了,我会再等一会儿,看看是否有人发布了一个更独立于编程语言的答案(就像一个公式)。
  • 我会尽快发布解释。
  • @Enrique 我已经添加了解释。希望它能让事情更清楚。您也可以将其转换为公式。事实上,我将其开发为一个公式,然后对其进行编码。
  • @Enrique 请考虑接受任何最适合您的答案。
【解决方案2】:

所以想要一个公式!行 !让我们来做一些简单的数学运算:

第 r 行的条目数是r*(r+1)/2。因此row 是满足row*(row+1)/2 &lt;= 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 移动一位。

【讨论】:

    【解决方案3】:

    你可以试试:

    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

    【讨论】:

    • 那是一个嵌套循环,我要getRow和getCol的公式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2019-12-06
    • 2013-03-29
    • 2017-03-25
    • 2016-10-31
    • 1970-01-01
    相关资源
    最近更新 更多