LeetCode 194. 转置文件
题目描述

题意分析
文件中每一行由空格分隔成若干字段,各行字段数量相同。要求将原文件每一列变成输出的一行,原来从上到下的字段顺序,变成输出行中从左到右的顺序。
原文件有多少列,结果就有多少行;每个输出行又包含原文件的全部行对应的字段。这里按字段转置,不是把文本按固定字符宽度切开,字段长度可以不同。
解法:awk 按列累积
核心思路
[!blue]
awk默认把每一行作为一条记录,NR是记录号,NF是当前行的字段数量,$i表示当前行第i个字段。利用这些内建信息,可以逐行读取,同时为各列分别积累输出。用
transposed[i]保存第i列已经读到的字段。处理完前r行后,这个字符串恰好包含前r行的第i个字段,并保持输入顺序;读取下一行时,只需把新的同列字段接到末尾,就能继续维持这个对应关系。第一行直接赋值,后续行才在已有内容与当前字段之间追加
OFS。OFS默认是单个空格,这样字段之间有分隔,输出行开头又不会多出空格。在第一行保存
columns = NF,文件读完后进入END,按照列号1..columns依次打印累积字符串。不能用关联数组的任意遍历顺序替代列号顺序,否则会把原列的位置打乱。空文件没有触发首行初始化,默认零列,结束阶段不会输出内容。
解题步骤
- 读取第一行时,将字段数保存为
columns。- 对每一行按列号访问
$i。第一行初始化该列字符串,其余行追加分隔空格与新字段。- 文件读取完后,在
END中从第1列依次打印到第columns列。- 每打印一个累积字符串就得到一行转置结果,全部列输出后结束。
代码实现
awk '
NR == 1 {
columns = NF
}
{
for (i = 1; i <= columns; i++) {
if (NR == 1) {
transposed[i] = $i
} else {
transposed[i] = transposed[i] OFS $i
}
}
}
END {
for (i = 1; i <= columns; i++) {
print transposed[i]
}
}
' file.txt
复杂度分析
设文件有
R行、C列,总文本长度为N。
- 时间复杂度:字段访问次数为 $O(RC)$;当前实现每次追加都会构造更长的累积字符串,计入复制成本时最坏为 $O(RN)$。字段长度固定时,最坏可写为 $O(CR^2)$。
- 空间复杂度:$O(N)$,当前实现保存各列的完整输出内容,待文件读完后按列打印。
关键点总结
[!green]
- 转置只交换行列角色,原列中字段的先后顺序保持不变。
$i读取当前行字段,transposed[i]保存对应输出行,两者配合完成按列积累。- 首行直接赋值,后续才加分隔符,避免前导空格。
- 输出循环以原列数为界,并显式按数值列号递增。
易错点总结
[!yellow]
- 用
NR控制输出行数,混淆了原行数和转置后的行数;转置后应按原列数输出。- 所有行都先拼接
OFS,会让每个输出行前面多一个空格。- 用
for (i in transposed)打印,关联数组没有保证列号递增顺序。- 把字段读取写成普通变量
i,拿到的是下标本身;动态读取字段应使用$i。- 按固定字符位置切列,无法正确处理长度不同的字段。
- 只按扫描字段的次数声称整体严格线性,会忽略累积字符串反复复制的成本。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 867. 转置矩阵 | 简单 | 转置关系相同,本题从文本逐行读入,用列缓冲生成输出而非直接访问二维数组。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!