如何打印方阵的右半球
Posted
技术标签:
【中文标题】如何打印方阵的右半球【英文标题】:How to print the right hemisphere of a square matrix 【发布时间】:2015-06-16 19:49:13 【问题描述】:我正在尝试打印矩阵的右半球。如果我们在矩阵中绘制主对角线和次对角线,我们会看到我们得到了 4 个相等的部分,右边的部分被称为(在我的算法教科书中)方阵的右半球。
例如,在下面的5 x 5
矩阵中,右半球由以下元素组成:-1, -3, -2, 0
。
我尝试解决此问题的方法是开始并组合第二对角线的一半,然后在左对角线元素的右侧打印每个元素。到达次对角线的中间后,我在主对角线的下部重复此过程。
类似的东西(至少,这是我在脑海中的看法):
这是一些打印5 x 5
矩阵右半球的工作代码。它可以工作,但是很难看,并且对于具有偶数行和列的矩阵(例如 4 x 4
矩阵)不能正常工作。
#include <iostream>
#define N 5
#define M 5
void printHemisphere(int matrix[N][M], int n, int m)
int i = 1;
for(int j = n - 1; j > n / 2; i++, j--)
for (int k = j + 1; k < m; ++k)
std::cout << matrix[i][k] << " ";
std::cout << std::endl;
for(int j = n / 2; j < n; i++, j++)
for (int k = j + 1; k < m; ++k)
std::cout << matrix[i][k] << " ";
std::cout << std::endl;
int main(int argc, char const *argv[])
int matrix5[N][M] =
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25
;
printHemisphere(matrix5, N, M);
return 0;
你会如何解决这个问题?
【问题讨论】:
这应该支持非方阵吗?如果有,怎么做? 不,它应该只适用于方阵。 【参考方案1】:我认为这应该适用于方阵:
void printHemisphere(int matrix[N][M], int n, int m)
int mid = n / 2;
for(int i = 1; i < mid; i++)
for (int j = n - i; j < m; ++j)
std::cout << matrix[i][j] << " ";
std::cout << std::endl;
for(int i = mid; i < n - 1; i++)
for (int j = i + 1; j < m; ++j)
std::cout << matrix[i][j] << " ";
std::cout << std::endl;
外部循环跳过第一行和最后一行,因为它们不能有输出。
【讨论】:
此解决方案与 marom 的问题相同。如果你尝试一下,你会看到输出只有12
,而它应该是8 12
。解决方案:对于j
,您应该使用n-1
而不是n
。因此,j 从(n-1)-i+1
= n-i
开始。此外,顶部的行在 [0, (N/2) -1] 范围内,底部的行在 [N/2, N-1] 范围内。所以,第一个循环可能是for(int i = 1; i < mid; i++)
,第二个循环可能是for(int i = mid; i < n - 1; i++)
。你可以在ideone.com/PzJOAN查看它
@FabioTurati - 感谢您对此进行测试(我应该在发布之前完成 - 让我感到羞耻)。我已经更新了我的代码来解决问题(包括消除伪造的k
下标)。
各位,非常感谢你们帮我解决这个问题。我不得不承认,这个解决方案对我来说并不是那么明显,我不得不稍微努力去理解它(真正意义上的)。您是否应用了一些模式来解决这类问题,或者只是靠直觉(通过实践发展)?
@cristid9 - 我以前处理过这种问题,所以我应用了经验。 (另外,正如在 cmets 中明显的,一些反复试验。)我不会把它美化为“模式”,因为它没有形式化或结构化,我不会称它为“直觉”,因为一个确实要考虑这些事情。这种情况下的技巧(如果你可以这么称呼它)是首先决定逐行处理矩阵,然后识别输出哪些行元素的条件在对角线交叉的位置发生变化。您自己的图表实际上显示了大部分已经完成的工作。【参考方案2】:
这是一种只使用双 for 循环的方法:
void printHemisphere(int matrix[N][M], int n, int m)
for(int i = 1; i < n - 1 ; i++)
for (j = max(i, n - i) ; j < m ; j++)
std::cout << matrix[i][k] << " ";
std::cout << std::endl;
std::cout << std::endl;
【讨论】:
总的来说,我喜欢这个答案,但有几点可以改进:1)您正在打印matrix[i][k]
,您的意思是matrix[i][j]
2)i
从 1 开始并停止在n-2
,但在矩阵中索引从 0 到 n-1
。这意味着您正在优化代码,知道可以跳过第一行和最后一行。很好,但我会把它写成评论 3) j
从 max(i, n-i)
开始的原因可以在评论中解释。我知道i
是主对角线在i
和另一条的n-i
处的坐标,max 基本上是最右边的,但你可以解释一下。
代码为4 x 4
矩阵输出错误结果:ideone.com/N9ElqS。它应该只打印8
和12
。
内循环应该从max(i, n - i) + 1
开始,而不是max(i, n - i)
。 OP 不想要对角线元素。
@TedHopp 你是对的,这种方法还包括对角线元素。但实际上它仍然是错误的。正确的公式是(int j = std::max(i, n - 1 - i) + 1;
。我之前的评论也错了:在i
行,次对角线的元素在n-1-i
,而不是n-i
。因此,虽然这种方法背后的总体思路是正确的,但代码需要一些调整。【参考方案3】:
在伪代码中...:
for row in 1 -> height - 2 // Indices between 0 -> height - 1
distance = min(row, height - 1 - row)
for cell in (width - distance) -> width - 1
print matrix[row][cell]
【讨论】:
你能解释一下distance = min(row, height - 1 - row)
的含义吗?我不确定我是否得到它。看起来distance
等于应该打印的元素数,对吗?
@cristid9 - 它“测量”与最近的“边缘行”(第一行,顶行 - 或最后一个,底行)的距离。对于远离边缘的每一行,您需要再打印 1 个水平单元格...【参考方案4】:
这是我的看法。我来晚了,因为您已经接受了解决方案;不过,我想向您展示一些东西。例如,如果您将这些矩阵视为一维数组,您可以只用一个函数测试所有大小的矩阵,因为大小不必“内置”到函数定义中的数据类型中。并且我已经评论了很多,希望尽可能的说清楚。
#include <iostream>
#include <algorithm>
// I store matrices as a monodimensional array, so that it is easier to deal
// with matrices of different sizes in the same program, because you can do
// everything with one function. Moreover, I use only one argument here, to make
// it clear that we are dealing with square matrices.
void printHemisphere(int* matrix, int last_row)
int last_column = last_row; // It's a square matrix, so they are the same.
// Still, distinguishing between last_column
// and last_row can make the algorithm clearer,
// so I have kept both
// In general I prefer to use "row" and "column" as variable names, instead
// of "i" and "j"
// Our rows go from 0 to last_row-1, but since the first and last one can
// certainly not be used, we can skip them: we start at row = 1, and we stop
// at last_row - 2 (that is, the last one for which row < last_row - 1)
for(int row = 1; row < last_row - 1 ; row++)
// We want to start from the cell to the right of the rightmost diagonal.
// The main diagonal has column = row;
// The secondary diagonal has column = last_row - 1 - row
// The rightmost one is the maximum of these 2.
// Then, we want to take the cell to the right of the diagonal, so we
// have to add 1 more.
// All in all we have:
for (int column = std::max(row, last_row - 1 - row) + 1;
column < last_column;
column++)
// since this is a 1-D array we have to access it this way
std::cout << matrix[row*last_row+column] << " ";
std::cout << std::endl;
std::cout << std::endl;
int main(int argc, char const *argv[])
// Since I am working with monodimensional arrays, I don't store them as
// int matrix3[3][3], but rather as int matrix3[9], which I have expressed as
// int matrix3[3*3] for clarity.
//For each one I have indicated the expected output.
// Expected output:
// 6
int matrix3[3*3] =
1, 2, 3,
4, 5, 6,
7, 8, 9
;
// Expected output:
// 8
// 12
int matrix4[4*4] =
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16
;
// Expected output:
// 10
// 14 15
// 20
int matrix5[5*5] =
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25
;
// Expected output:
// 12
// 17 18
// 23 24
// 30
int matrix6[6*6] =
1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36
;
// Expected output:
// 14
// 20 21
// 26 27 28
// 34 35
// 42
int matrix7[7*7] =
1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49
;
printHemisphere(matrix3, 3);
printHemisphere(matrix4, 4);
printHemisphere(matrix5, 5);
printHemisphere(matrix6, 6);
printHemisphere(matrix7, 7);
return 0;
我已经在 ideone 上验证了它,它可以工作。我唯一想补充的是:为确保代码正常工作,请确保使用奇数大小和偶数大小的矩阵对其进行测试。
【讨论】:
以上是关于如何打印方阵的右半球的主要内容,如果未能解决你的问题,请参考以下文章