很棒的讲解https://www.youtube.com/watch?v=TYokkbftEx8
这道题的意思跟i最大的区别就是要连续call的话,不再每次读都从头开始,而是从上一次读完的地方开始。
比如text stream = "abcdefg"
我们之前只call一次的read(4)就会得到buf = [abcd];再call read(6)又会得到buf = [abcdef]; 但现在我们call multiple times的话,read(4)会得到buf = [abcd], 再read(2)的话就会得到buf = [ef]. 就是这个区别。
根据题意,头脑里会想到这下子肯定需要一个pointer来表示我们读到了文件的哪里,但是题目没有input stream, 所以要动脑筋想怎么用现有的输入来完成这个。这就要求我们把char[] temp, count, pointer作为全局变量,这样我们屡次call read()的时候这些量不会变。 为什么index不需要成为全局变量呢,因为每次read都要返回实际读过的数index, 所以是函数内部的局部变量。比如上面的例子里,我们第一次call read(4), 那么首先我们检查pointer是否为0, 为零的意思是我们已经读完了之前得到的char[4] temp, (因为pointer就是用来遍历temp的,只有读完了我们才会重置为0)。
如果pointer为零我们就要重新调用read4得到新的temp和更新count. 此时如果得到的count为零,说明没有可以再读的内容,我们跳出循环返回index。如果不为零,我们就开始读写(读temp写入buf). 这里我们要注意控制while循环的执行条件,一是显而易见的index < n因为我们不能读超过max = n的数,同时还要保证pointer < count, 因为我们的temp只有count这么多个数,你读不了更多。循环体内部就是读写步骤buf[index++] = temp[i++]; 最后检查pointer 是否等于count, 等于的话说明这个temp被读完了。如果pointer 不等于count,但index已经等于n了,是什么情况呢?比如temp = [abcd], 想要得到的buf = [ab],则我们的pointer会等于2,不会等于count = 4. 这时候我们的pointer, count因为是全局变量,可以在下一次call的时候继续利用。
比如这时候我们再call read(2),实际上此时pointer就不等于0,而是等于2.那么我们就不需要新读出一个temp, 而是要继续读完上一次没读完的temp. 直接进入while 循环继续读写。得到buf[cd]的时候刚好index == n并且pointer == count.这时候pointer == count我们要重置pointer. 最后返回index.
/* 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
*/
/*
"abcdefgh"
index = 0; pointer = 0
n = 2 temp = [abcd] count = 4
buf[ab]
*/ public int pointer = 0;
public int count = 0;
public char[] temp = new char[4];
public int read(char[] buf, int n) {
int index = 0;
while (index < n){
if (pointer == 0){
count = read4(temp);
}
if (count == 0){
break;
}
while (index < n && pointer < count){
buf[index++] = temp[pointer++];
}
if (pointer == count){
pointer = 0;
}
}
return index;
}
}