PIO12. 单组 二维字符数组
题目描述
给定一个 n 行 m 列的二维字符数组 A(仅含小写英文字符), 请你对「行和列都倒置」,然后输出。
输入格式
第一行有两个整数 n 和 m。 随后 n 行,每行有 m 个字符,仅包含小写英文字符。
输出格式
输出倒置后的二维字符数组,共 n 行,每行 m 个字符。
示例
示例 1
输入:
3 4
abcd
efgh
ijkl
输出:
lkji
hgfe
dcba
说明:
原矩阵第一行 abcd 经过「行、列都倒置」后跑到了最后一行,
并且自身也反了过来,变成 dcba;其余行同理。
解题思路
第一步:理解问题本质
「行和列都倒置」听起来像两件事,其实等价于把整个矩阵旋转 180°:
- 行倒置:最后一行移到第一行,第一行移到最后一行;
- 列倒置:每一行内部的字符顺序反转。
第二步:拆成两步手动做
如果不用技巧,可以写成:
rows = rows[::-1] # 行倒置
rows = [row[::-1] for row in rows] # 每行再倒置
逻辑清楚,但要遍历两遍。
第三步:合并成一次遍历(推荐)
把两步合并到一个推导式里:
out = [row[::-1] for row in reversed(rows)]
reversed(rows) 从最后一行开始遍历,每行再做一次 [::-1]。
一次遍历就完成,代码也更紧凑。
完整代码实现
算法可视化 · 逐帧回放这道题的代码3 帧 · 录制输入
import sys
def solve() -> None:
"""把二维字符数组旋转 180° 后输出"""
data = sys.stdin.read().split()
if not data:
return
n = int(data[0])
m = int(data[1]) # 列数:每行字符串长度天然是 m
rows = data[2:2 + n]
# 行倒置 + 每行倒置
out = [row[::-1] for row in reversed(rows)]
sys.stdout.write("\n".join(out) + "\n")
if __name__ == "__main__":
solve()
示例推演
原矩阵:
abcd
efgh
ijkl
第一步,行倒置得到:
ijkl
efgh
abcd
第二步,每行内部倒置:
lkji
hgfe
dcba
结果与样例一致。
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 分两步 | O(n*m) | O(n*m) | 直观 |
| 合并一次遍历 | O(n*m) | O(n*m) | 推荐,代码更短 |
n 为行数,m 为列数。
易错点总结
1. 只倒置一次
只做行倒置或只做列倒置都会错。题目要求两者都做, 等价于旋转 180°,不是转置(转置是行列互换,形状会变)。
2. 用 split() 读含空格的字符数组
本题字符之间没有空格,所以 read().split() 可以直接按行切分;
但如果某行字符之间带空格,就必须逐行读并 replace(" ", "")。
3. 输出时把每行拼成一个字符串
倒置后每行仍然是「每个字符写在一起」,不要把字符用空格分开输出。
扩展思考
- 顺时针旋转 90°、逆时针旋转 90° 都是「行倒置 / 列倒置 / 转置」的组合。
- 转置需要先构造
m行n列的新矩阵,形状会变化,和本题不同。