
前言
为什么普通的 Scanner 会超时?
我们平时写练习常用 Scanner sc = new Scanner(System.in),但在笔试 / 算法题中 90% 会超时。
原因:
**Scanner**效率极低:底层同步、解析慢,面对大量输入数据直接超时。- 换行、空格处理弱:连续空格、空行、多行输入容易读错。
- 大数据量下性能差距巨大 :
BufferedReader比Scanner快 5~10 倍。
所以:只要是笔试 / 算法题,一律使用「快读模板」。
- 避免超时 :笔试时间限制严格,
Scanner必挂。 - 格式稳定:自动处理多空格、空行、多行输入。
- 不越界 :
StringTokenizer不会像split()那样切出空数组。 - 通用万能:一套模板走所有题型(整数、小数、字符串、多行、多组数据)。
快读三个核心类
BufferedReader(缓冲字符输入流)
- 作用 :带缓冲区的高效读取,一次性读一大块数据,而不是一个字符一个字符读。
- 核心方法 :
readLine()------ 读取一整行字符串。 - 优势:速度极快,是 Java 最快的读取方式之一。
StringTokenizer(字符串分词器)
-
作用 :把一行字符串按空格 / 换行 / 制表符自动切割成一个个单词(token)。
-
核心方法:
-
hasMoreTokens():是否还有下一个单词nextToken():取下一个单词
-
优势 :✅ 自动处理任意多个连续空格 ✅ 自动处理换行错乱 ✅ 不会数组越界✅ 比
split()更快更稳
PrintWriter(缓冲打印输出流)
- 作用 :比
System.out.println更快的输出方式,带缓冲。 - 核心方法 :
print()/println()/printf()/flush() - 优势:大量输出时不卡顿,不超时。
java
import java.io.*;
import java.util.*;
// 万能快读模板
public class Main {
public static void main(String[] args) throws IOException {
// 快读
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 快写
PrintWriter out = new PrintWriter(System.out);
// 分词器(自动切分空格/换行)
StringTokenizer st = new StringTokenizer(br.readLine());
// ===================== 下面写你的代码 ======================
// 示例:读取一个整数
int n = Integer.parseInt(st.nextToken());
out.println(n);
// ==========================================================
out.flush(); //刷新缓存区,输出
br.close(); //关闭流
out.close();
}
}
常见模式
直接输出
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
out.print("Hello Nowcoder!");
out.flush();
}
}
a+b
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
StringTokenizer st=new StringTokenizer(br.readLine());
int a=Integer.parseInt(st.nextToken());
int b=Integer.parseInt(st.nextToken());
out.print(a+b);
out.flush();
}
}
多组_A+B_T组形式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
//这里只有一个n,直接读就行
int n=Integer.parseInt((br.readLine()));
while(n-->0){
StringTokenizer st=new StringTokenizer(br.readLine());
int a=Integer.parseInt(st.nextToken());
int b=Integer.parseInt(st.nextToken());
out.println(a+b);
}
out.flush();
}
}
多组_A+B_EOF
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
// StringTokenizer st=new StringTokenizer(br.readLine());
String line;
while((line=br.readLine())!=null){
// line=line.trim();//去掉这一行前后的空格、换行、空白
// String[] s=line.split("\\s+"); //按"任意空白"分割成字符数组
String[] s=line.split(" "); //分割
int a=Integer.parseInt(s[0]);
int b=Integer.parseInt(s[1]);
out.println(a+b);
}
out.flush();
}
}
也可以不分割
java
String line;
while ((line = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
System.out.println(a + b);
}
多组_A+B_零尾模式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
// StringTokenizer st=new StringTokenizer(br.readLine());
String line;
while((line=br.readLine())!=null){
// line=line.trim();//去掉这一行前后的空格、换行、空白
// String[] s=line.split("\\s+"); //按"任意空白"分割成字符数组
String[] s=line.split(" "); //分割
int a=Integer.parseInt(s[0]);
int b=Integer.parseInt(s[1]);
if(a==0&&b==0) break;
out.println(a+b);
}
out.flush();
}
}
数组
单组_一维数组
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int n = Integer.parseInt(br.readLine()); // 读第一行 n
StringTokenizer st = new StringTokenizer(br.readLine()); // 读第二行数组
long sum = 0;
for (int i = 0; i < n; i++) {
sum += Long.parseLong(st.nextToken());
}
out.println(sum);
out.flush();
br.close();
}
}
多组_一维数组_T组形式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t = Integer.parseInt(br.readLine()); // 读第一行 n
while(t-->0){
int n = Integer.parseInt(br.readLine()); // 读第一行 n
StringTokenizer st = new StringTokenizer(br.readLine());
long sum = 0;
for (int i = 0; i < n; i++) {
sum += Long.parseLong(st.nextToken());
}
System.out.println(sum);
}
out.flush();
br.close();
}
}
单组_二维数组
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
StringTokenizer st=new StringTokenizer(br.readLine());
int n=Integer.parseInt(st.nextToken());
int m=Integer.parseInt(st.nextToken());
long sum=0;
for(int i=0;i<n;i++){
st=new StringTokenizer(br.readLine()); //输入一行
for(int j=0;j<m;j++){
sum+=Long.parseLong(st.nextToken());
}
}
out.print(sum);
out.flush();
br.close();
}
}
多组_二维数组_T组形式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t=Integer.parseInt(br.readLine());
while(t-->0){
StringTokenizer st=new StringTokenizer(br.readLine());
int n=Integer.parseInt(st.nextToken());
int m=Integer.parseInt(st.nextToken());
long sum=0;
for(int i=0;i<n;i++){
st=new StringTokenizer(br.readLine()); //输入一行
for(int j=0;j<m;j++){
sum+=Long.parseLong(st.nextToken());
}
}
out.println(sum);
}
out.flush();
br.close();
}
}
字符串
单组_字符串
- 加反转
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t=Integer.parseInt(br.readLine());
String s = br.readLine();
String s2=new StringBuilder(s).reverse().toString();
out.print(s2);
out.flush();
br.close();
}
}
多组_字符串_T组形式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t=Integer.parseInt(br.readLine());
while(t-->0){
int n=Integer.parseInt(br.readLine());
String s = br.readLine();
String s2=new StringBuilder(s).reverse().toString();
out.println(s2);
}
out.flush();
br.close();
}
}
单组_二维字符数组
比较麻烦,参考一下
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
StringTokenizer st=new StringTokenizer(br.readLine());
int n=Integer.parseInt(st.nextToken());
int m=Integer.parseInt(st.nextToken());
char[][] arr=new char[n][m];
for(int i=0;i<n;i++){
arr[i]=br.readLine().toCharArray();
}
//倒置行顺序
for(int i=0;i<n/2;i++){
char[] tmp=arr[i];
arr[i]=arr[n-1-i];
arr[n-1-i]=tmp;
}
// 再倒置每行
for (int i = 0; i < n; i++) {
for (int j = 0; j < m / 2; j++) {
char tmp = arr[i][j];
arr[i][j] = arr[i][m - 1 - j];
arr[i][m - 1 - j] = tmp;
}
}
for(int i=0;i<n;i++){
out.println(new String(arr[i]));
}
out.flush();
br.close();
}
}
多组_带空格的字符串_T组形式
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t=Integer.parseInt(br.readLine());
while(t-->0){
int n=Integer.parseInt(br.readLine());
String[] s = br.readLine().split("\\s+");
StringBuilder ss=new StringBuilder();
for(int i=s.length-1;i>=0;i--){
ss.append(new StringBuilder(s[i]).reverse());
}
out.println(ss.toString());
}
out.flush();
br.close();
}
}
格式和简单判断
单组_保留小数位数
给定一个小数 nn ,请你保留 33 位小数后输出。
如果原来的小数位数少于 33 ,需要补充 00 。
如果原来的小数位数多于 33 ,需要四舍五入到 33 位。
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
//这里只有一个n,直接读就行
double n=Double.parseDouble((br.readLine()));
out.printf("%.3f",n);
out.flush();
br.close();
}
}
单组_补充前导零
描述
给定一个正整数 nn ,请你保留 99 个数位,然后输出。
如果数位少于 99 个,那么需要补充前导零。
输入描述:
第一行有一个整数 n ( 1≤n<10的9次 ) 。
输出描述:
输出一个数字,保留 9个数位。
比如:
输入:123
输出:000000123
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
//这里只有一个n,直接读就行
int n=Integer.parseInt((br.readLine()));
out.printf("%09d",n);
out.flush();
br.close();
}
}
单组_spj判断YES与NO
java
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
int n = Integer.parseInt(br.readLine());
// 判断奇偶
if (n % 2 == 1) {
out.println("YES");
} else {
out.println("NO");
}
out.flush();
br.close();
}
}