Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 157. Read N Characters Given Read4 #157

Open
grandyang opened this issue May 30, 2019 · 2 comments
Open

[LeetCode] 157. Read N Characters Given Read4 #157

grandyang opened this issue May 30, 2019 · 2 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

Given a file and assume that you can only read the file using a given method read4, implement a method to read  n  characters.

 

Method read4:

The API read4 reads 4 consecutive characters from the file, then writes those characters into the buffer array buf.

The return value is the number of actual characters read.

Note that read4() has its own file pointer, much like FILE *fp in C.

Definition of read4:

    Parameter:  char[] buf
    Returns:    int

Note: buf[] is destination not source, the results from read4 will be copied to buf[]

Below is a high level example of how read4 works:

File file("abcdefghijk"); // File is "abcdefghijk", initially file pointer (fp) points to 'a'
char[] buf = new char[4]; // Create buffer with enough space to store characters
read4(buf); // read4 returns 4. Now buf = "abcd", fp points to 'e'
read4(buf); // read4 returns 4. Now buf = "efgh", fp points to 'i'
read4(buf); // read4 returns 3. Now buf = "ijk", fp points to end of file

 

Method read:

By using the read4 method, implement the method read that reads  n  characters from the file and store it in the buffer array buf. Consider that you cannot manipulate the file directly.

The return value is the number of actual characters read.

Definition of read:

    Parameters:	char[] buf, int n
    Returns:	int

Note: buf[] is destination not source, you will need to write the results to buf[]

 

Example 1:

Input: file = "abc", n = 4
Output: 3
Explanation: After calling your read method, buf should contain "abc". We read a total of 3 characters from the file, so return 3. Note that "abc" is the file's content, not buf. buf is the destination buffer that you will have to write the results to.

Example 2:

Input: file = "abcde", n = 5
Output: 5
Explanation: After calling your read method, buf should contain "abcde". We read a total of 5 characters from the file, so return 5.

Example 3:

Input: file = "abcdABCD1234", n = 12
Output: 12
Explanation: After calling your read method, buf should contain "abcdABCD1234". We read a total of 12 characters from the file, so return 12.

Example 4:

Input: file = "leetcode", n = 5
Output: 5
Explanation: After calling your read method, buf should contain "leetc". We read a total of 5 characters from the file, so return 5.

 

Note:

  1. Consider that you cannot manipulate the file directly, the file is only accesible for read4 but not for read.
  2. The read function will only be called once for each test case.
  3. You may assume the destination buffer array, buf, is guaranteed to have enough space for storing  n  characters.

 

这道题给了我们一个 Read4 函数,每次可以从一个文件中最多读出4个字符,如果文件中的字符不足4个字符时,返回准确的当前剩余的字符数。现在让实现一个最多能读取n个字符的函数。这题有迭代和递归的两种解法,先来看迭代的方法,思路是每4个读一次,然后把读出的结果判断一下,如果为0的话,说明此时的 buf 已经被读完,跳出循环,直接返回 res 和n之中的较小值。否则一直读入,直到读完n个字符,循环结束,最后再返回 res 和n之中的较小值,参见代码如下:

 

解法一:

// Forward declaration of the read4 API.
int read4(char *buf);

class Solution {
public:
    int read(char *buf, int n) {
        int res = 0;
        for (int i = 0; i <= n / 4; ++i) {
            int cur = read4(buf + res);
            if (cur == 0) break;
            res += cur;
        }
        return min(res, n);
    }
};

 

下面来看递归的解法,这个也不难,对 buf 调用 read4 函数,然后判断返回值t,如果返回值t大于等于n,说明此时n不大于4,直接返回n即可,如果此返回值t小于4,直接返回t即可,如果都不是,则直接返回调用递归函数加上4,其中递归函数的 buf 应往后推4个字符,此时n变成n-4即可,参见代码如下:

 

解法二:

// Forward declaration of the read4 API.
int read4(char *buf);

class Solution {
public:
    int read(char *buf, int n) {
        int t = read4(buf);
        if (t >= n) return n;
        if (t < 4) return t;
        return 4 + read(&buf[4], n - 4);
    }
};

 

Github 同步地址:

#157

 

类似题目:

Read N Characters Given Read4 II - Call multiple times

 

参考资料:

https://leetcode.com/problems/read-n-characters-given-read4/

https://leetcode.com/problems/read-n-characters-given-read4/discuss/49557/Accepted-clean-java-solution

https://leetcode.com/problems/read-n-characters-given-read4/discuss/49496/Another-accepted-Java-solution

 

LeetCode All in One 题目讲解汇总(持续更新中...)

@lld2006
Copy link

lld2006 commented Jun 4, 2020

我觉得你这个solution其实是有问题的, 我用read的时候给一个char *, 其实read的api只要提供一个n+1 byte的字符串数组就够了。 比如n=5, 但是read4的时候, 用上面的程序可能读到8个byte, 这样就存在内存越界的问题。 我个人认为, 最好当n <4 的时候, 用一个5个byte的char[] 去读,然后写到buf里面需要的byte数目。

@JW9506
Copy link

JW9506 commented Mar 12, 2021

我觉得你这个solution其实是有问题的, 我用read的时候给一个char *, 其实read的api只要提供一个n+1 byte的字符串数组就够了。 比如n=5, 但是read4的时候, 用上面的程序可能读到8个byte, 这样就存在内存越界的问题。 我个人认为, 最好当n <4 的时候, 用一个5个byte的char[] 去读,然后写到buf里面需要的byte数目。

老哥, 你觉得你真的理解对了么? 我看上去解法1解法2都没问题啊.
buf是调用函数前准备好的. 而就针对这个题目而言, 是oj提前准备好的.
你可能是在问 'n不是4的整数倍' 的情况buf会溢出对吧? 解决办法就是让buf足够大(例如向上取整4的整数倍), 然后读前n个不就行了?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants