157. Read N Characters Given Read4
挺有意思的一道题。FB钟爱的两道系统操作模拟题,157,158。
这题的 API 和题目描述都有点模糊,重新理一下:
int read4(char[] buf)
你扔一个 char[] 过去,函数写入最多 4 个 char 在上面,然后返回写入 char 的长度; 到文件末尾的时候返回 char 长度会小于 4
于是我们的目标是把最终长度为 n 的字符串写入自己函数的 read(char[] buf) 里,然后返回实际长度。
主要的注意点就是,有的时候 read4 是短板,有的时候 readN 自己是短板(不需要4个那么多的字符),在写入的时候要注意处理下。
/* The read4 API is defined in the parent class Reader4.
int read4(char[] buf); */
public class Solution extends Reader4 {
/**
* @param buf Destination buffer
* @param n Maximum number of characters to read
* @return The number of characters read
*/
public int read(char[] buf, int n) {
boolean EOF = false;
char[] tmp = new char[4];
int curPtr = 0;
while (curPtr < n && !EOF) {
int charCount = read4(tmp);
EOF = charCount < 4;
for (int i = 0; i < charCount && curPtr < n; ++i) {
buf[curPtr++] = tmp[i];
}
}
return curPtr;
}
}
158. Read N Characters Given Read4 II - Call multiple times
多次调用之后,这题的难点就变成了 “如何处理剩余字符”。因为一次 call 拿到的字符很可能超过我们实际需要的,这时候就需要依赖外部 buffer 记录下来,每次新 read() call 的时候,先从缓存里拿。
我们只用一个 buffer,大小为 4. 因为一次读取的字符数量不会超过 4,而且每次 read() 之后剩余的字符数量也不会超过 4.
因此这一个全局 buffer,就代表了我们全部的可用字符,一个 int 存数量,一个 int 存起点。
需要写入 buffer 的时候就写,如果没有了,就向 read4 要,到时候 ptr 会自动记录下一轮的起始位置和剩余字符串数量。
/* The read4 API is defined in the parent class Reader4.
int read4(char[] buf); */
public class Solution extends Reader4 {
/**
* @param buf Destination buffer
* @param n Maximum number of characters to read
* @return The number of characters read
*/
char[] tmp = new char[4];
int bufPtr = 0;
int bufCount = 0;
int bufEnd = 0;
public int read(char[] buf, int n) {
int curPtr = 0;
while (curPtr < n) {
if (bufCount == 0) {
bufCount = read4(tmp);
bufEnd = bufCount;
bufPtr = 0;
}
if (bufCount == 0) break;
while (curPtr < n && bufPtr < bufEnd) {
buf[curPtr++] = tmp[bufPtr++];
bufCount--;
}
}
return curPtr;
}
}