从1 x n向量生成n x n-1矩阵,其中第i行是没有第i个元素的向量,没有for循环

时间:2016-02-05 00:03:27

标签: performance matlab matrix vectorization matrix-multiplication

拉格朗日多项式我需要这个。我很好奇在没有for循环的情况下如何做到这一点。代码目前看起来像这样:

tj = 1:n;
ti = zeros(n,n-1);
for i = 1:n
    ti(i,:) = tj([1:i-1, i+1:end]);
end

我的tj实际上不仅仅是1:n向量,但这并不重要。虽然这个for循环完成了工作,但我宁愿使用一些矩阵运算。我试着寻找一些合适的矩阵来增加它,但到目前为止没有运气。

3 个答案:

答案 0 :(得分:4)

这是一种方式:

v = [10 20 30 40]; %// example vector
n = numel(v);
M = repmat(v(:), 1, n);
M = M(~eye(n));
M = reshape(M,n-1,n).';

给出

M =
    20    30    40
    10    30    40
    10    20    40
    10    20    30

答案 1 :(得分:1)

这应该推广到任何n

ti = flipud(reshape(repmat(1:n, [n-1 1]), [n n-1]));

仔细看看发生了什么。如果你仔细观察结果矩阵,你会从下往上看到它是n-1 1,n-1 2等。

适用于n为3的情况。

ti =

     2     3
     1     3
     1     2

所以我们可以垂直翻转并获得

f = flipud(ti);

     1     2
     1     3
     2     3

实际上这是[1, 2, 3; 1, 2, 3]重塑为3 x 2而不是2 x 3。

在那条思路中

a = repmat(1:3, [2 1])

     1     2     3
     1     2     3

b = reshape(a, [3 2]);

     1     2
     1     3
     2     3

c = flipud(b);

     2     3
     1     3
     1     2

我们现在回到你把它们放在一起的地方,用n代替3,用n-1代替2。

答案 2 :(得分:0)

这是另一种方式。首先创建一个矩阵,其中每一行是向量tj但是堆叠在彼此之上。接下来,提取矩阵的下三角部分和上三角部分而不对角线,然后将结果相加,确保删除下三角矩阵的最后一列和上三角矩阵的第一列。

n = numel(tj);
V = repmat(tj, n, 1);
L = tril(V,-1);
U = triu(V,1);
ti = L(:,1:end-1) + U(:,2:end); 

numel找到我们存储在tj中的n中的值总数。 repmat有助于堆叠向量tj以创建n x n大的矩阵。之后,我们使用triltriu,以便我们提取矩阵的下三角和上三角部分,而不是对角线。此外,除相关的三角形部分外,矩阵的其余部分均为零。 -11的{​​{1}}和tril标志分别成功提取出来,同时确保对角线全为零。这会在调用triu时在最后一列显示一列额外的零,而在调用tril时会创建第一列。最后一部分是简单地将这两个矩阵一起添加,忽略triu结果的最后一列和tril结果的第一列。

鉴于triu(借用Luis Mendo的例子),我们得到:

tj = [10 20 30 40];