我确实对此考虑了很多,并且能够弄清楚所有变量和计数器的运行方式以及我们如何得出结果。
但是,是否有任何逻辑支持Mark Byer的解决方案here,或者是否只是调整以便所有计数器都到位?
请给我一个算法的逻辑解释
代码
#include <stdio.h>
int main()
{
int x[3][3] = {1, 2, 3,
4, 5, 6,
7, 8, 9};
int n = 3;
for (int slice = 0; slice < 2 * n - 1; ++slice) {
printf("Slice %d: ", slice);
int z = slice < n ? 0 : slice - n + 1;
for (int j = z; j <= slice - z; ++j) {
printf("%d ", x[j][slice - j]);
}
printf("\n");
}
return 0;
}
答案 0 :(得分:1)
Mark的回答是正确的,适用于任何n
。也许Mark应该将变量diagonal
命名为slice
而不是n = 3
。
看看对角线的方式&#39;对于 start ->
end a - b - c
| | |
\/ h d
| |
g - f - e
:
a-b-c-d-e
对于每个对角线,起始索引遵循路径:a-h-g-f-e
,结束索引遵循路径:a-a
。并且为了穿越对角线,我们需要沿西南方向行进,即我们访问的每个下一点是下方的一行和向左的一列。因此,对角线为:b-h
,c-g
,d-f
,e-e
,n + (n - 1) = 2 * n - 1
。
对于初学者来说,当我们以任何一种方式跑出界限时,你可以想到结束每个对角线的遍历(记住,我们正在增加行并减少列,总是)。 Mark的回答也在循环变量中捕获了它。
我们还需要看到对角线的数量始终为d# start end
----------------------
0 (0, 0) (0, 0)
1 (0, 1) (1, 0)
2 (0, 2) (2, 0)
3 (1, 2) (2, 1)
4 (2, 2) (2, 2)
。
下表列出了上述对角线图片:
end
现在,既然我们知道了start
(即西南方向的进展直到我们用完了界限),我们总能捕获d#
,我们需要关注{{1}的关系与start
一起使用。
如果您为n = 4
绘制了类似的图表/表格,也许您可以看到该模式并按照d#
捕获第一个循环的变量。