
题目考点
这道题主要考:
- 字符串对齐方法:
rjust()、ljust()、center() - 字符串重复:
'H' * n for循环控制行数- 把一个复杂图形拆成几块分别打印
这道题看起来图案很复杂,但本质不是算法题,而是“根据模板补对齐方法”的题。
审题
题目给我们一个整数 thickness,表示 logo 的厚度。题目说明:
The thickness must be an odd number.
也就是说输入一定是奇数,比如 5、7、9。
输出要求是打印一个 HackerRank 的 H 形 logo。
这个 logo 可以拆成 5 个部分:
1. 上面的尖角 Top Cone
2. 上面的两根柱子 Top Pillars
3. 中间横杠 Middle Belt
4. 下面的两根柱子 Bottom Pillars
5. 下面的倒尖角 Bottom Cone
所以做题时不要一整张图一起想。应该把它看成 5 个小图形,分别处理。
思路提示
这道题的核心思路是:
先不要急着写代码,先观察每一块图形应该“往哪边对齐”。
第一块:Top Cone
顶部是一个逐渐变宽的三角形:
H
HHH
HHHHH
HHHHHHH
HHHHHHHHH
它的特点是:中间有一个固定的 H,左边和右边分别逐渐增加 H。
所以它需要:
左边部分:右对齐 rjust()
中间部分:固定一个 H
右边部分:左对齐 ljust()
第二块:Top Pillars
上面的柱子大概长这样:
HHHHH HHHHH
HHHHH HHHHH
HHHHH HHHHH
左柱和右柱都是一组 'H' * thickness。
它们需要在不同宽度里面居中,所以用:
center()
第三块:Middle Belt
中间横杠是一大条:
HHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHH
这一整条也要放在中间位置,所以继续用:
center()
第四块:Bottom Pillars
下面的柱子和上面的柱子一样:
HHHHH HHHHH
HHHHH HHHHH
所以也用:
center()
第五块:Bottom Cone
底部是一个倒过来的尖角:
HHHHHHHHH
HHHHHHH
HHHHH
HHH
H
这一整块整体靠右,所以最后需要整体再用一次:
rjust()
完整设计思路
假设输入:
thickness = 5
c = 'H'
我们不是直接打印一整张图,而是分 5 段打印。
1. 打印顶部尖角
循环:
for i in range(thickness):
当 thickness = 5 时,i 会依次是:
0, 1, 2, 3, 4
每一行的左边是:
c * i
所以分别是:
''
'H'
'HH'
'HHH'
'HHHH'
顶部每一行由三部分拼起来:
(c * i).rjust(thickness - 1) + c + (c * i).ljust(thickness - 1)
也就是:
左边部分 + 中间H + 右边部分
2. 打印上面的柱子
上面的柱子有 thickness + 1 行。
每一行由两个柱子组成:
(c * thickness).center(thickness * 2)
+
(c * thickness).center(thickness * 6)
其中:
c * thickness
如果 thickness = 5,就是:
'HHHHH'
3. 打印中间横杠
中间横杠的高度是:
(thickness + 1) // 2
如果 thickness = 5:
(5 + 1) // 2 = 3
所以打印 3 行。
每一行是:
(c * thickness * 5).center(thickness * 6)
如果 thickness = 5:
c * thickness * 5
就是:
'H' * 25
4. 打印下面的柱子
下面柱子和上面柱子完全一样,所以代码也一样。
5. 打印底部倒尖角
底部倒尖角要从宽到窄,所以循环里用:
thickness - i - 1
当 thickness = 5 时:
i = 0 -> 4
i = 1 -> 3
i = 2 -> 2
i = 3 -> 1
i = 4 -> 0
也就是 H 的数量逐渐减少。
最后整行还要整体向右对齐,所以外面再套一个:
.rjust(thickness * 6)
代码实现
这道题在 HackerRank 上原本是让你把空白处替换成 rjust、ljust 或 center。完整代码如下:
thickness = int(input())
c = 'H'
# Top Cone
for i in range(thickness):
print((c * i).rjust(thickness - 1) + c + (c * i).ljust(thickness - 1))
# Top Pillars
for i in range(thickness + 1):
print((c * thickness).center(thickness * 2) + (c * thickness).center(thickness * 6))
# Middle Belt
for i in range((thickness + 1) // 2):
print((c * thickness * 5).center(thickness * 6))
# Bottom Pillars
for i in range(thickness + 1):
print((c * thickness).center(thickness * 2) + (c * thickness).center(thickness * 6))
# Bottom Cone
for i in range(thickness):
print(((c * (thickness - i - 1)).rjust(thickness) + c + (c * (thickness - i - 1)).ljust(thickness)).rjust(thickness * 6))
关键方法解释
rjust(width)
表示右对齐。
'H'.rjust(5)
结果类似:
H
总长度是 5,H 在最右边,左边补空格。
ljust(width)
表示左对齐。
'H'.ljust(5)
结果类似:
H
总长度是 5,H 在最左边,右边补空格。
center(width)
表示居中对齐。
'H'.center(5)
结果类似:
H
总长度是 5,H 在中间,两边补空格。
运行演示
假设输入:
5
程序中:
thickness = 5
c = 'H'
顶部尖角部分:
当 i = 0:
(c * 0).rjust(4) + 'H' + (c * 0).ljust(4)
也就是:
H
当 i = 1:
(c * 1).rjust(4) + 'H' + (c * 1).ljust(4)
也就是:
HHH
当 i = 2:
HHHHH
所以顶部逐渐变宽。
中间柱子部分,每一行都是两个:
'HHHHH'
只不过通过 center() 控制它们的位置。
底部倒尖角部分刚好反过来,从:
HHHHHHHHH
逐渐变成:
H
并且整体靠右。
方法总结
这类题不要从整张图开始硬想,而要按下面顺序处理:
第一步,先把图形拆成几块。
第二步,观察每一块是靠左、靠右,还是居中。
第三步,确定每一块每一行打印多少个字符。
第四步,用 for 循环控制行数。
第五步,用 rjust()、ljust()、center() 控制位置。
这道题最重要的不是记住完整代码,而是学会:复杂图形题通常都可以拆成多个小区域,每个小区域再用循环和字符串对齐方法解决。
小练习
请你自己尝试打印下面这个图形,输入一个奇数 n,例如 n = 5:
*
***
*****
*******
*********
提示:
- 每一行星号数量是奇数:
1, 3, 5, 7, 9 - 可以用
'*' * 某个数量生成星号 - 可以用
center()让每一行居中 - 总宽度可以设置成
2 * n - 1



