The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
Note:
The read function may be called multiple times.
157. Read N Characters Given Read4 的拓展,之前只能调用一次,而这里可以调用多次,又多了一些corner case:
第一次调用时,如果read4读出的多余字符我们要先将其暂存起来,这样第二次调用时先读取这些暂存的字符
第二次调用时,如果连暂存字符都没读完,那么这些暂存字符还得留给第三次调用时使用
所以,难点就在于怎么处理这个暂存字符。因为用数组和指针控制对第二种情况比较麻烦,且这些字符满足先进先出,所以我们可以用一个队列暂存这些字符。这样,只要队列不为空,就先读取队列。
Java: Time: O(n), Space: O(1)
public class Solution extends Reader4 {
Queue<Character> remain = new LinkedList<Character>();
public int read(char[] buf, int n) {
int i = 0;
// 队列不为空时,先读取队列中的暂存字符
while(i < n && !remain.isEmpty()){
buf[i] = remain.poll();
i++;
}
for(; i < n; i += 4){
char[] tmp = new char[4];
int len = read4(tmp);
// 如果读到字符多于我们需要的字符,需要暂存这些多余字符
if(len > n - i){
System.arraycopy(tmp, 0, buf, i, n - i);
// 把多余的字符存入队列中
for(int j = n - i; j < len; j++){
remain.offer(tmp[j]);
}
// 如果读到的字符少于我们需要的字符,直接拷贝
} else {
System.arraycopy(tmp, 0, buf, i, len);
}
// 同样的,如果读不满4个,说明数据已经读完,返回总所需长度和目前已经读到的长度的较小的
if(len < 4) return Math.min(i + len, n);
}
// 如果到这里,说明都是完美读取,直接返回n
return n;
}
}
Python:
class Solution(object):
def __init__(self):
self.__buf4 = [''] * 4
self.__i4 = 0
self.__n4 = 0
def read(self, buf, n):
"""
:type buf: Destination buffer (List[str])
:type n: Maximum number of characters to read (int)
:rtype: The number of characters read (int)
"""
i = 0
while i < n:
if self.__i4 < self.__n4: # Any characters in buf4.
buf[i] = self.__buf4[self.__i4]
i += 1
self.__i4 += 1
else:
self.__n4 = read4(self.__buf4) # Read more characters.
if self.__n4:
self.__i4 = 0
else: # Buffer has been empty.
break
return i
if __name__ == "__main__":
global file_content
sol = Solution()
buf = ['' for _ in xrange(100)]
file_content = "ab"
print(buf[:sol.read(buf, 1)])
print(buf[:sol.read(buf, 2)])
Python:
from Queue import Queue
class Solution(object):
def __init__(self):
#self.curTotal = 0
self.buffer = Queue()
self.endOfFile = False
def read(self, buf, n):
"""
:type buf: Destination buffer (List[str])
:type n: Maximum number of characters to read (int)
:rtype: The number of characters read (int)
"""
if n == 0:
return 0
total = 0
while self.buffer.qsize() < n and not self.endOfFile:
temp = [""] * 4
r = read4(temp)
if r < 4:
self.endOfFile = True
for i in range(r):
self.buffer.put(temp[i])
for i in range(min(self.buffer.qsize(), n)):
buf[i] = self.buffer.get()
total += 1
return total
C++:
int read4(char *buf);
class Solution {
public:
/**
* @param buf Destination buffer
* @param n Maximum number of characters to read
* @return The number of characters read
*/
int read(char *buf, int n) {
if(n == 0)
return 0;
int total = 0;
while(this->buffer.size() < n && !this->endOfFile) {
char* temp = new char[4];
int r = read4(temp);
if(r < 4)
this->endOfFile = true;
for(int i = 0; i < r; i++)
this->buffer.push(temp[i]);
}
int l = min((int)this->buffer.size(), n);
for(int i = 0; i < l; i++) {
buf[i] = this->buffer.front();
this->buffer.pop();
total++;
}
return total;
}
private:
queue<char> buffer;
bool endOfFile = false;
};
相关题目: