某大厂员工吐槽:单位新来的00后嫌椅子不舒服,自己买了把一千多人体工学椅,老员工看到后沉默了,自己忍了十几年只买了靠垫!
新来的00后也是真敢整。刚入职没几天,先嫌公司椅子坐着腰疼,转头自己下单一把一千多的人体工学椅,第二天直接搬到工位。旁边那帮老员工看了一眼,集体“啧啧啧”,然后全沉默了。
老一辈打工人那套逻辑就是:忍,凑合,垫个靠垫已经算对自己好了。腰不舒服?那就站起来走两步。脖子酸?说明最近活多。反正十几年都这么熬过来了。
结果00后不跟你演这个苦情戏。坐得不舒服,我就换。身体是自己的,班是公司的。评论区也有人说,这代人不是娇气,是算明白账了,花一千块保住腰,比以后去医院理疗便宜多了。还有人补刀,说老员工不是不想买,是早被“能用就行”这四个字驯服了。
面试题:转置文件
文件一大,很多人第一反应就是把所有内容先读进 List<String>,再按列去拼。这个写法在本地跑小样例没问题,真丢到几十 MB 甚至更大的文本上,内存先开始不老实。
“转置文件”这题其实不复杂,难点不在算法本身,在你是不是一上来就把题目想歪了。它本质上不是矩阵转置,也不是二维数组题,而是按行读、按列吐。输入像这样:
name age city
tom 18 bj
jack 20 sh
转置后要变成:
name tom jack
age 18 20
city bj sh
也就是说,第 1 行的第 1 个单词、第 2 行的第 1 个单词、第 3 行的第 1 个单词,最后要落到同一行里。
我一般先盯两个点:
第一,分隔符是不是固定空格。很多人直接 split(" "),这就埋坑了,连续空格会切出空串。这里更稳一点,直接上 split("\\s+")。
第二,不同行的字段数可能不一样。你以为每行都是 3 列,结果线上文件第四行少个字段,代码就数组越界了。这种题别太信输入一定规整,防一手不吃亏。这个判断习惯,做久了线上排障自然就有了。
下面这版我自己会这么写,思路很直接:先把每一行拆成数组,顺手记下最大列数;然后第二轮按列拼接输出。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
publicclassMain{
publicstaticvoidmain(String[] args)throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
List<String[]> rows = new ArrayList<>();
String line;
int maxCols = 0;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) {
continue;
}
String[] parts = line.split("\\s+");
rows.add(parts);
if (parts.length > maxCols) {
maxCols = parts.length;
}
}
StringBuilder out = new StringBuilder();
for (int col = 0; col < maxCols; col++) {
StringBuilder currentLine = new StringBuilder();
for (String[] row : rows) {
if (col < row.length) {
if (currentLine.length() > 0) {
currentLine.append(' ');
}
currentLine.append(row[col]);
}
}
out.append(currentLine).append('\n');
}
System.out.print(out);
}
}
这段代码有几个地方是故意这么写的。
line.trim() 先收一下,避免首尾空格影响判断。空行直接跳过,不参与转置,不然后面会多出一些莫名其妙的空列。
maxCols 单独记,不要后面临时扫,不然逻辑散。还有一点,输出时我没在循环里硬控最后一个空格,而是通过 currentLine.length() > 0 来决定要不要补空格,这种写法比“先拼接再删最后一个空格”稳,少一点边界判断。
时间复杂度不高,核心就是遍历两遍单词,算 O(m * n),m 是行数,n 是最大列数。空间复杂度主要花在存储原始分词结果上。
当然,这题还有人喜欢边读边转,把第 1 列、第 2 列、第 3 列分别塞到不同的 StringBuilder 里,那样也能做,而且更省一次遍历。只是代码会稍微绕一点,面试里未必划算。题不大,先把正确性和边界守住,比炫技巧重要。
这种题看着像字符串处理,真写起来,翻车点永远还是那些:空格、空行、列数不齐。代码短,不代表可以糊弄。