题目分析
最初级的输出图形题就是直白地说明要输出几行,而这一题给的是输出的总数,所以要先从给定的N
推算出要输出几行。而能输出的行数和给出的N
是有严格的数学关系式的。
假设给定N
个符号,从顶层到中层的层数是n
,总层数是M
,那么有:
n
=
N
+
1
2
,
M
=
2
n
2
−
1
n = \sqrt{\frac{N+1}{2}},\ M = 2n^2 - 1
n=2N+1, M=2n2−1
对于每一行需要输出两种元素,分别是空格和给定的字符。空格依次递增后递减,步长1个,初始为0个;给定字符依次递减后递增,步长2个,初始为M
个。若序号从0开始,转折点都在第M/2+1
处开始发生(即M/2
及之前都是递减状态)。
算法实现
前面计算M, n, N
的地方就是数学计算,稍微复杂的是每一行怎么去输出。关键在知道每一行输出的空格和指定字符是多少
- 对于前
M/2
行- 空格数:起始是0,每次递增1,这和序列号
i
的规律一样,所以可以写成输出i
个 - 字符数:起始是
M
,每次递减2,所以可以写成输出M-2i
个
- 空格数:起始是0,每次递增1,这和序列号
- 对于
M/2+1
行及之后:去找它的对照行,表达式为M/2-(i-M/2)
*但是注意此处的是程序中的数学表达式,在程序中的M/2
运算过后会自动减0.5,所以写的时候如果合并,要自动减去1,写作M-i-1
实现如下:
for(i = 0; i < M; i++) {
// I = i <= M/2 ? i : M - 1 - i;
I = (i < M / 2) ? i : M/2 - (i - M/2);
for(j = 0; j < I; j++) {
printf(" ");
}
for(k = 0; k < M - 2 * I; k++) {
printf("%c", c);
}
printf("\n");
}