[LeetCode] 158. 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.

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;
};

  

   

相關題目:

[LeetCode] 157. Read N Characters Given Read4 用Read4來讀取N個字符 

 


免責聲明!

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



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