我正在尝试为以下问题提出非暴力解决方案。给定一个任意大小的矩阵:
[6 0 3 5]
[3 7 1 4]
[1 4 8 2]
[0 2 5 9]
将其对角线转换为向量列表,如下所示:
(0)
(1, 2)
(3, 4, 5)
(6, 7, 8, 9)
(0, 1, 2)
(3, 4)
(5)
(在本例中从左下角到右上角)
有没有一种优雅的方法可以做到这一点,而不是迭代左列和顶行?
我只想写一个小函数来将向量索引转换为矩阵索引。
说矩阵是NxN
方阵,那么就会有2N-1
向量;如果我们将向量从0
到编号,则向量的2N-2
元素将位于行和列(或者相反,行、列的矩阵元素将是向量的元素)。然后,每当您需要访问向量的元素时,只需将坐标从转换为(即,将向量索引转换为矩阵索引)并访问矩阵的适当元素。而不是实际上有一个向量列表,你会得到一些模仿的东西k
n
max(N-1-n+k,k)
max(n+k-N+1,k)
i
j
min(i,j)
N-1+j-i
k,n
i,j
向量列表,从某种意义上说,它可以为您提供列表中任何向量的任何所需元素 - 这确实同样好。(欢迎鸭子打字;-)
但是,如果您要访问矩阵的每个元素,迭代可能会更快,而不是每次都进行此计算。
(非检查代码)像这样的东西(java代码):
// suppose m is the matrix, so basically an int[][] array with r rows and c columns
// m is an int[rows][cols];
List result = new ArrayList(rows + cols - 1);
for (int i = 0; i < (rows + cols - 1))
{
int y;
int x;
if (i < rows)
{
x = 0;
y = rows - i - 1;
}
else
{
x = i - rows + 1;
y = 0;
}
Vector v = new Vector();
while (y < rows && x < cols)
{
y++;
x++;
v.add(new Integer(m[y][c]));
}
result.add(v);
}
// result now contains the vectors you wanted
编辑:我把 x 和 y 弄混了,现在更正了。
数学:
m = {{6, 0, 3, 5},
{3, 7, 1, 4},
{1, 4, 8, 2},
{0, 2, 5, 9}};
Table[Diagonal[m, i], {i, 1 - Length@m, Length@m[[1]] - 1}]
它给出了第 i 个对角线的列表,其中第 0 个对角线是主对角线,i = -1 给出它下面的一个,等等。换句话说,它返回:
{{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {0, 1, 2}, {3, 4}, {5}}
当然,使用内置Diagonal
功能是一种作弊。这是Diagonal
从头开始的实现:
(* Grab the diagonal starting from element (i,j). *)
diag0[m_,i_,j_] := Table[m[[i+k, j+k]], {k, 0, Min[Length[m]-i, Length@m[[1]]-j]}]
(* The i'th diagonal -- negative means below the main diagonal, positive above. *)
Diagonal[m_, i_] := If[i < 0, diag0[m, 1-i, 1], diag0[m, 1, i+1]]
该Table
函数基本上是一个收集到列表中的 for 循环。例如,
Table[2*i, {i, 1, 5}]
返回{2,4,6,8,10}
。