LeetCode 158 - Read N Characters Given Read4 II


LeetCode 157 - Read N Characters Given Read4
https://cheonhyangzhang.wordpress.com/2016/12/22/158-leetcode-java-read-n-characters-given-read4-ii-call-multiple-times-add-to-list-questioneditorial-solution-hard/
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.
The difference between this question and the first version is that the read() function will be called multiple times.
The trouble here will be as the following example if using the first version solution:
file: “abcdefg”
read(3) read(2) read(2) should be “abc” “de” “fg”
but using first version solution it will print “abc” “ef” “”
This is because when you use read4() to read, the pointer to read file has already moved to “e” after the first call of read4(). So it’s not correct any more.
In order to solve, we need to persist the characters that has been already read by using read4 but it’s not put into the result of read().
In the solution below, I am using a buf4[] to store the characters read by using read4 and also a buf4Size and buf4Index to keep track of the size of the buf4 and the next character to use in buf4[].
[LeetCode] Read N Characters Given Read4 II | 程序员达达
[分析]
跟之前的一道题目比,这一题要复杂不少。主要是因为read函数可以调用多次以后,有可能文件中的部分内容被读出来,但是暂时没有用到。因此需要额外的空间来缓存读出来的字符。
[注意事项]
1)对于几个变量的解读:
- buffer 存储从文件中读出来的字符
- offset 上一次读取之后buffer中剩下字符的偏移量
- bufsize buffer中剩下字符的个数

https://discuss.leetcode.com/topic/6402/clean-accepted-java-solution
    private int offSet = 0;
    private int remaining = 0;
    private boolean isEndOfFile = false;
    private char[] buffer = new char[4];
    public int read(char[] buf, int n) {
        int readBytes = 0;
        while (readBytes < n && (remaining != 0 || !isEndOfFile)) {
            int readSize = 0;
            if (remaining != 0) {
                readSize = remaining;
            } else {
                offSet = 0;
                readSize = read4(buffer);
                if (readSize != 4) {
                    isEndOfFile = true;
                }
            }
            int length = Math.min(n - readBytes, readSize);
            for (int i= offSet; i<offSet + length; i++) {
                buf[readBytes++] = buffer[i];
            }
            remaining = readSize - length;
            if (remaining != 0) {
                offSet += length;
            }
        }
        return readBytes;
    }
http://yuanhsh.iteye.com/blog/2186426
  1. private char[] buffer = new char[4];  
  2. private int offset = 0, bufsize = 0;   
  3. public int read(char[] buf, int n) {  
  4.     int total = 0;  
  5.     boolean eof = false;  
  6.     while (!eof && total < n) {  
  7.         if (bufsize == 0) {  
  8.             bufsize = read4(buffer);  
  9.             if (bufsize < 4) {  
  10.                 eof = true;  
  11.             }  
  12.         }  
  13.         int bytes = Math.min(n - total, bufsize);   
  14.         System.arraycopy(buffer /*src*/, offset /*srcPos*/,   
  15.                          buf /*dest*/,   total /*destPos*/,   
  16.                          bytes /*length*/);  
  17.         offset = (offset + bytes) % 4;  
  18.         bufsize -= bytes;  
  19.         total += bytes;  
  20.     }  
  21.     return total;  
  22. }  

   private char [] buffer = new char[4];
   int offset = 0, bufsize = 0; 
   public int read(char[] buf, int n) {
      int readBytes = 0;
      boolean eof = false;
      while (!eof && readBytes < n) {
          int sz = (bufsize>0)? bufsize : read4(buffer);
          if (bufsie==0 && sz < 4) eof = true;
          int bytes = Math.min(n - readBytes, sz); 
          System.arraycopy(buffer /* src */, offset /* srcPos */, buf /* dest */, 
                 readBytes /* destPos */, bytes /* length */);
          offset = (offset + bytes) % 4;
          bufsize = sz - bytes;
          readBytes += bytes;
    }
      return readBytes;
   }
https://leetcode.com/discuss/19581/clean-accepted-java-solution
The key is to store memorized variable in the class level and remember offset position and remaining number of elements.
private int offSet = 0; private int remaining = 0; private boolean isEndOfFile = false; private char[] buffer = new char[4]; public int read(char[] buf, int n) { int readBytes = 0; while (readBytes < n && (remaining != 0 || !isEndOfFile)) { int readSize = 0; if (remaining != 0) { readSize = remaining; } else { offSet = 0; readSize = read4(buffer); if (readSize != 4) { isEndOfFile = true; } } int length = Math.min(n - readBytes, readSize); for (int i= offSet; i<offSet + length; i++) { buf[readBytes++] = buffer[i]; } remaining = readSize - length; if (remaining != 0) { offSet += length; } } return readBytes; }
https://leetcode.com/discuss/40768/java-solution-no-if-s
public class Solution extends Reader4 {
    private char[] buffer = new char[4];
    private int bufferBytes = 0;
    private int bufferPointer = 0;

    public int read(char[] buf, int n) {
        int copy = Math.min(n, bufferBytes);
        System.arraycopy(buffer, bufferPointer, buf, 0, copy);
        bufferBytes -= copy;
        bufferPointer += copy;

        int total = copy;
        int readBytes = 4;
        while (total < n && readBytes == 4) {
            readBytes = read4(buffer);
            copy = Math.min(n-total, readBytes);
            bufferBytes = readBytes - copy;
            bufferPointer = copy;
            System.arraycopy(buffer, 0, buf, total, copy);
            total += copy;
        }

        return total;
    }
}
  1. copying data from the buffer;
  2. copying data from the underlying stream;
  3. maintain bufferPointer/bufferBytes in the both sections. No if(s).
http://www.cnblogs.com/EdwardLiu/p/4240616.html


 其实我觉得可以只用一个offset作为instance variable,而不用再用一个oneRead, 因为offset+oneRead = 4
X. Use Queue
https://leetcode.com/discuss/22982/java-solution-with-clean-comments
Use a queue to store the character being left by last read. And first check the queue before a new read
private Queue<Character> lastLeft = new LinkedList<Character>(); public int read(char[] buf, int n){ int i = 0; int bufferLength = 0, readLength = 4; char[] buffer = new char[4]; // pop the last left characters first while(i < n && !lastLeft.isEmpty()){ buf[i++] = lastLeft.poll(); } // read in new characters while(i < n){ if(bufferLength==0){ bufferLength = read4(buffer); readLength = bufferLength; } buf[i++] = buffer[readLength-(bufferLength--)]; if(readLength < 4 && bufferLength==0) return i; } // push the remaining into queue for next use while(bufferLength!=0){ queue.add(buffer[bufferLength--]); } return i; }
http://segmentfault.com/a/1190000003794420
因为要调用多次,这里又多了一些corner case:
  1. 第一次调用时,如果read4读出的多余字符我们要先将其暂存起来,这样第二次调用时先读取这些暂存的字符
  2. 第二次调用时,如果连暂存字符都没读完,那么这些暂存字符还得留给第三次调用时使用
所以,难点就在于怎么处理这个暂存字符。因为用数组和指针控制对第二种情况比较麻烦,且这些字符满足先进先出,所以我们可以用一个队列暂存这些字符。这样,只要队列不为空,就先读取队列。
    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;
    }

https://changhaz.wordpress.com/2014/11/24/leetcode-read-n-characters-given-read4-ii-call-multiple-times/
Related LeetCode 157 - Read N Characters Given Read4
Read full article from [LeetCode] Read N Characters Given Read4 II | 程序员达达

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts