我最近看到一个贴子,直接把我整笑了。有人说:“我代码都没合并,测试说他测完了……”这话听着就离谱。
作为一名开发,看到这种场景真是又好气又好笑。测试提前踩点,这是想“先占个坑再说”?
但话说回来,这事其实不罕见。写代码的都懂,我们埋头改需求、修bug,测试却在那边标个“已完成”。要是没沟通清楚进度,最后出了问题,锅还不是甩到开发头上。
所以我觉得吧,开发和测试之间的信任和协作才是重中之重,不然总有人在“勇敢试探”和“被动背锅”之间游走。
今日算法题
好了,吃完瓜,我们说说算法题,最近刷题的时候,我碰到了一个题,叫“用 Read4 读取 N 个字符 II - 多次调用”。光看名字,就感觉像是在念舌绕题,但其实它并没有那么复杂,今天我就跟大家聊聊这道题。
先从基础讲起吧。题目给了我们一个 read4
方法,这个方法每次能从某个文件里读取最多 4 个字符。它的签名一般是这样的:
int read4(char[] buf4);
buf4
是一个长度为 4 的字符数组,用来存放读取的字符。如果文件中剩下的字符不足 4 个,那它会只读剩下的字符,返回读取的实际数量。
这题的核心是要实现一个新的 read
方法:
int read(char[] buf, int n);
它能让用户多次调用,逐步从文件中读取指定数量的字符。而这里的难点就在于,read4
是一次性读取 4 个字符的,我们得想办法把这些字符合理分配到多次调用中。
用大白话总结一下问题:我们手上有个工具(read4
),每次给我们最多 4 个字符,但用户可能每次只要 1 个,或者想分多次拿走某个数量的字符。为了完成这个任务,我们得设计一个缓冲区,把每次多出来的字符存起来,等下一次调用再用上。
好,下面开始写代码:
class Solution {
constructor() {
this.buffer = []; // 缓冲区,用来存放多余的字符
}
read(buf, n) {
let total = 0; // 记录本次读取了多少字符
while (total < n) {
if (this.buffer.length === 0) {
// 缓冲区空了,需要调用 read4
let tempBuf = new Array(4); // 临时存放 read4 的结果
let count = read4(tempBuf); // 调用 read4 获取字符
if (count === 0) {
// 文件读取完了,直接退出
break;
}
// 把读取到的字符放到缓冲区
this.buffer.push(...tempBuf.slice(0, count));
}
// 从缓冲区中取字符
while (this.buffer.length > 0 && total < n) {
buf[total++] = this.buffer.shift();
}
}
return total; // 返回实际读取的字符数
}
}
如果你看完代码还是懵的话,别急,我来拆解一下思路:
我们维护了一个缓冲区
this.buffer
,用来存储每次调用read4
多出来的字符。比如,调用read4
读了 4 个字符,但用户只需要 2 个,那多出来的 2 个就丢到缓冲区里。每次调用
read
时,先从缓冲区拿字符,如果缓冲区不够,就调用read4
去读更多字符。读完
read4
后,把结果存到缓冲区,并继续从中取字符,直到满足用户需求或者文件读完。
这么做有什么好处呢?就是无论用户调用 read
的方式多奇葩,我们都能通过缓冲区保存状态,确保不会漏读或者重复读字符。
举个例子,假设文件内容是 "abcdefg"
,用户分三次调用 read
,每次分别需要 1、5、1 个字符。我们看一下代码是怎么工作的:
第一次调用:
缓冲区为空,调用 read4
,读到"abcd"
。用户只需要 1 个字符,返回 "a"
,剩下"bcd"
存进缓冲区。第二次调用:
缓冲区有 "bcd"
,调用read4
,读到"efg"
。用户需要 5 个字符,从缓冲区拿 "bcd"
,再从新读取的字符中拿"ef"
,返回"bcdef"
,剩下"g"
存进缓冲区。第三次调用:
缓冲区有 "g"
,用户只需要 1 个字符,直接从缓冲区拿"g"
,返回。
整个过程就是这么循环往复,直到文件读完。
再强调几点细节:
缓冲区的作用是核心,没有它,我们没法处理用户分次调用 read
的情况。每次调用 read4
都是大操作,所以尽量只在缓冲区不够用时调用,能减少不必要的开销。最终返回的字符数不能超过 n
,这个需求我们通过total
变量控制。
写到这里,我觉得这道题的核心其实是“状态管理”——如何用缓冲区保存上次调用的状态,并在下次调用时继续利用。这个技巧在很多场景里都用得到,尤其是流处理或者分块读取数据的时候。
怎么样,是不是没想象中那么难?
目前,对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥私藏精品 热门推荐 虎哥作为一名老码农,整理了全网最全《前端资料合集》。