【问题标题】:Make an n x n-1 matrix from 1 x n vector where the i-th row is the vector without the i-th element, without a for loop从 1 x n 向量创建一个 n x n-1 矩阵,其中第 i 行是没有第 i 个元素的向量,没有 for 循环
【发布时间】:2016-02-05 00:03:26
【问题描述】:
我需要这个用于拉格朗日多项式。我很好奇如果没有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 循环完成了工作,但我宁愿使用一些矩阵运算。我尝试寻找一些合适的矩阵来与之相乘,但到目前为止没有运气。
【问题讨论】:
标签:
performance
matlab
matrix
vectorization
matrix-multiplication
【解决方案1】:
这是一种方法:
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
【解决方案2】:
这应该推广到任何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
我们现在又回到了您开始的地方,我们将所有内容整合在一起,将 3 替换为 n,将 2 替换为 n-1。
【解决方案3】:
这是另一种方式。首先创建一个矩阵,其中每一行都是向量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 大的矩阵。之后,我们使用tril 和triu 来提取矩阵的下三角部分和上三角部分没有对角线。此外,除相关的三角形部分外,矩阵的其余部分均为零。 tril 和 triu 的 -1 和 1 标志分别成功地提取了它,同时确保对角线全为零。这会在调用 tril 时创建一列额外的零,在调用 triu 时出现在第一列。最后一部分是简单地将这两个矩阵相加,忽略tril 结果的最后一列和triu 结果的第一列。
鉴于 tj = [10 20 30 40];(借用 Luis Mendo 的示例),我们得到:
ti =
20 30 40
10 30 40
10 20 40
10 20 30