LeetCode 付费题157. 用 Read4 读取 N 个字符解题思路
问题描述
实现一个 read
方法,通过给定的 read4
API 从文件中读取最多 n
个字符到目标缓冲区 buf
中。read4
每次从文件读取最多4个字符到临时缓冲区。
核心思路
- 循环读取机制:
- 通过多次调用
read4
分批读取数据 - 每次读取后,将临时缓冲区的数据复制到目标缓冲区
- 重复直到满足以下任一条件:
- 读取字符数达到
n
- 文件读取完毕(
read4
返回0)
- 读取字符数达到
- 通过多次调用
- 关键变量:
idx
:记录已复制到buf
的字符数(目标缓冲区索引)tmpBuf
:临时缓冲区(固定大小4),存储read4
的返回结果cnt
:每次read4
实际读取的字符数(0~4)
算法步骤
-
初始化:
- 目标缓冲区索引
idx = 0
- 创建临时缓冲区
tmpBuf = new char[4]
- 目标缓冲区索引
-
循环读取:
while (idx < n) {int cnt = read4(tmpBuf); // 读取最多4个字符if (cnt == 0) break; // 文件结束// 复制数据到目标缓冲区for (int i = 0; i < cnt; i++) {buf[idx + i] = tmpBuf[i];}idx += cnt; // 更新已复制字符数 }
-
返回结果:
- 实际读取字符数为
min(idx, n)
- 文件结束但未读满
n
时,返回实际读取量
- 实际读取字符数为
边界处理
- 文件不足
n
字符:当read4
返回0时提前终止循环 - 读取超
n
字符:通过idx < n
循环条件控制 - 缓冲区溢出防护:
Math.min(idx, n)
确保返回值不超过n
复杂度分析
- 时间复杂度:
- 循环次数:
O(⌈n/4⌉)
- 字符复制:
O(n)
- 总时间复杂度:
O(n)
- 循环次数:
- 空间复杂度:
- 临时缓冲区
tmpBuf
:O(4) = O(1)
- 总空间复杂度:
O(1)
- 临时缓冲区
示例说明
假设文件内容为 "abcdef"
,n=5
:
- 第一次
read4
→tmpBuf="abcd"
,cnt=4
- 复制到
buf[0:3]
,idx=4
- 复制到
- 第二次
read4
→tmpBuf="ef"
,cnt=2
- 复制到
buf[4:5]
,idx=6
- 复制到
- 返回
min(6,5)=5
→buf="abcde"
适用场景
- 需要从流中分批读取数据的场景
- 目标缓冲区大小受限时
- 文件大小未知的情况(自动处理文件结束)
注:此解法严格遵循题目要求,高效处理字符读取和缓冲区管理,时间和空间复杂度均为最优。
完整代码
public class Solution extends Reader4 {/*** @param buf Destination buffer* @param n Number of characters to read* @return The number of actual characters read*/public int read(char[] buf, int n) {int idx = 0;char[] tmpBuf = new char[4];while (idx < n) {int cnt = read4(tmpBuf);if (cnt == 0) break;for (int i = 0; i < cnt; i++) buf[idx + i] = tmpBuf[i];idx += cnt;}return Math.min(idx, n);}
}