Leetcode: Read N Characters Given Read4 II - Call multiple times


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.

Show Tags
Have you met this question in a real interview?

這道題跟I不一樣在於,read函數可能多次調用,比如read(buf,23)之后又read(buf, 25), 第一次調用時的buffer還沒用完,還剩一個char在buffer里,第二次拿出來接着用,這樣才能保證接着上次讀的地方繼續往下讀。

1. 所以應該設置這4個char的buffer為instance variable(實例變量),這樣每次調用read函數后buffer還剩的元素可以被保存下來,供給下一次讀取

2. 那么下一次調用read函數時候,怎么知道上一次buffer里面還剩不剩未讀元素呢?我們有oneRead(一次讀到buffer里的char數),actRead(實際被讀取的char數),oneRead-actRead就是還剩在buffer里的char數。通常oneRead == actRead, 只有當n-haveRead < oneRead時,才不等,這就是上一次調用read結束的時候。所以只要調用read函數發現oneRead != 0 時,就說明上一次調用read還剩了元素在buffer里,先讀完這個,再調用read4讀新的。oneRead也需要是instance varaible

3. 還需要設置一個offset: Use to keep track of the offset index where the data begins in the nextread call. The buffer could be read partially (due to constraints of reading upto n bytes) and therefore leaving some data behind.

                      |<--buffer-->|   
    // |_________________________|
    // |<---offset---> |<----oneRead--->

上圖所示為一次read最后的情況,offset部分其實就是actRead的部分,oneRead = oneRead - actRead, 就剩下了右邊一部分在buffer里沒有讀,下一次read函數調用,發現oneRead>0, 說明上一次read還剩了一部分沒有讀。oneRead表示的其實就是上一次讀剩下的char數,offset表示這一次讀應該開始的位置

其實上圖的oneRead不一定會充滿整個右邊部分的,有可能上一次讀oneRead根本沒有讀滿整個buffer。 所以oneRead+offset並不一定等於整個buffer。這也就是為什么我們一定要用兩個變量oneRead\offset的原因,因為oneRead並不一定=4-offset

 1 /* The read4 API is defined in the parent class Reader4.
 2       int read4(char[] buf); */
 3 
 4 public class Solution extends Reader4 {
 5     /**
 6      * @param buf Destination buffer
 7      * @param n   Maximum number of characters to read
 8      * @return    The number of characters read
 9      */
10      private char buffer = new char[4];
11      private int oneRead = 0;
12      private int offset = 0;
13      
14      public int read(char[] buf, int n) {
15          boolean lessthan4 = false;
16          int haveRead = 0;
17          while (!lessthan4 && haveRead < n) {
18              if (oneRead == 0) {
19                  oneRead = read4(buffer);
20                  lessthan4 = oneRead < 4;
21              }
22              int actRead = Math.min(n-haveRead, oneRead);
23              for (int i=0; i<actRead; i++) {
24                  buf[haveRead+i] = buffer[offset+i];
25              }
26              oneRead -= actRead;
27              offset = (offset + actRead) % 4;
28              haveRead += actRead;
29          }
30          return haveRead;
31      }
32 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM