Skip to content

算法笔试处理输入输出


BufferReader

普通读

java
package class019;

// 展示acm风格的测试方式
// 子矩阵的最大累加和问题,不要求会解题思路,后面的课会讲
// 每一组测试都给定数据规模
// 任何空间都提前生成好,一律都是静态空间,然后自己去复用,推荐这种方式
// 测试链接 : https://www.nowcoder.com/practice/cb82a97dcd0d48a7b1f4ee917e2c0409?
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code,提交时请把类名改成"Main",可以直接通过

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Code03_StaticSpace {

	// 题目给定的行的最大数据量
	public static int MAXN = 201;

	// 题目给定的列的最大数据量
	public static int MAXM = 201;

	// 申请这么大的矩阵空间,一定够用了
	// 静态的空间,不停复用
	public static int[][] mat = new int[MAXN][MAXM];

	// 需要的所有辅助空间也提前生成
	// 静态的空间,不停复用
	public static int[] arr = new int[MAXM];

	// 当前测试数据行的数量是 n
	// 当前测试数据列的数量是 m
	// 这两个变量可以把代码运行的边界规定下来
	public static int n, m;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StreamTokenizer in = new StreamTokenizer(br);
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		while (in.nextToken() != StreamTokenizer.TT_EOF) {
			// 注意强制类型转换
			n = (int) in.nval;
			in.nextToken();
			m = (int) in.nval;
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					in.nextToken();
					mat[i][j] = (int) in.nval;
				}
			}
			out.println(maxSumSubmatrix());
		}
		out.flush();
		br.close();
		out.close();
	}

	// 求子矩阵的最大累加和,后面的课会讲
	public static int maxSumSubmatrix() {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < n; i++) {
			// 因为之前的过程可能用过辅助数组
			// 为了让之前结果不干扰到这次运行,需要自己清空辅助数组需要用到的部分
			Arrays.fill(arr, 0, m, 0);
			for (int j = i; j < n; j++) {
				for (int k = 0; k < m; k++) {
					arr[k] += mat[j][k];
				}
				max = Math.max(max, maxSumSubarray());
			}
		}
		return max;
	}

	// 求子数组的最大累加和,后面的课会讲
	public static int maxSumSubarray() {
		int max = Integer.MIN_VALUE;
		int cur = 0;
		for (int i = 0; i < m; i++) {
			cur += arr[i];
			max = Math.max(max, cur);
			cur = cur < 0 ? 0 : cur;
		}
		return max;
	}
}

按行读

适用读取字符串

java
package class019;

// 展示acm风格的测试方式
// 测试链接 : https://www.nowcoder.com/exam/test/70070648/detail?pid=27976983
// 其中,7.A+B(7),就是一个没有给定数据规模,只能按行读数据的例子
// 此时需要自己切分出数据来计算
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code,提交时请把类名改成"Main",可以直接通过

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class Code04_ReadByLine {

	public static String line;

	public static String[] parts;

	public static int sum;

	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		while ((line = in.readLine()) != null) {
			parts = line.split(" ");
			sum = 0;
			for (String num : parts) {
				sum += Integer.valueOf(num);
			}
			out.println(sum);
		}
		out.flush();
		in.close();
		out.close();
	}
}

Kattio

java
package class019;

// 本文件课上没有讲,介绍一下Kattio类的使用
// 某些题目的输入,使用StreamTokenizer就是无法正确读入
// 那么可以使用本文件提供的Kattio类
// 比如,就是需要依次读取一个一个的字符串进行处理
// 再比如,StreamTokenizer读取:不溢出、但是很大的long类型数字时,可能会读入错误
// 再比如,StreamTokenizer读取:科学计数法表达的double类型数字时,可能会读入错误
// 如果使用Kattio进行读取,就没有这些问题
// 可以直接运行本文件的main函数,根据提示输入给定的数字,能清晰的看到这一点
// 那么可不可以放弃StreamTokenizer,以后都用Kattio呢?
// 不行!因为StreamTokenizer的效率还是比Kattio好!
// 只有在StreamTokenizer无法正确读取的情况下,才考虑使用Kattio类
// 其他语言中一定有对等的概念,不是java的同学,请自行搞定

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.StringTokenizer;

public class Code05_Kattio {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StreamTokenizer in = new StreamTokenizer(br);
		System.out.println("请输入 : 131237128371723187");
		System.out.println("并按回车");
		in.nextToken();
		long long1 = (long) in.nval;
		System.out.println("StreamTokenizer读取到的数字 : ");
		System.out.println(long1);
		System.out.println();
		System.out.println("请输入 : 5.6920E+0001");
		System.out.println("并按回车");
		in.nextToken();
		double double1 = in.nval;
		System.out.println("StreamTokenizer读取到的数字 : ");
		System.out.println(double1);

		System.out.println("============================");

		Kattio io = new Kattio();
		System.out.println("请输入 : 131237128371723187");
		System.out.println("并按回车");
		long long2 = io.nextLong();
		System.out.println("Kattio读取到的数字 : ");
		System.out.println(long2);
		System.out.println();
		System.out.println("请输入 : 5.6920E+0001");
		System.out.println("并按回车");
		double double2 = io.nextDouble();
		System.out.println("Kattio读取到的数字 : ");
		System.out.println(double2);
		io.close();
	}

	// 如何使用Kattio的简单示例
	// 可以找个一些具体题目试一试
	// 这里就是罗列了一下
	public static void show() {
		Kattio io = new Kattio(); // 自动接入输入输出流
		io.next(); // 读取下一个字符串,注意不是整行,是以空格或回车分割的字符串,一个一个读取
		io.nextInt(); // 读取下一个int
		io.nextDouble(); // 读取下一个double
		io.nextLong(); // 读取下一个long
		io.println("ans"); // 答案进入输出流
		io.flush(); // 答案刷给后台
		io.close(); // 关闭io
	}

	// Kattio类IO效率很好,但还是不如StreamTokenizer
	// 只有StreamTokenizer无法正确处理时,才考虑使用这个类
	// 参考链接 : https://oi-wiki.org/lang/java-pro/
	public static class Kattio extends PrintWriter {
		private BufferedReader r;
		private StringTokenizer st;

		public Kattio() {
			this(System.in, System.out);
		}

		public Kattio(InputStream i, OutputStream o) {
			super(o);
			r = new BufferedReader(new InputStreamReader(i));
		}

		public Kattio(String intput, String output) throws IOException {
			super(output);
			r = new BufferedReader(new FileReader(intput));
		}

		public String next() {
			try {
				while (st == null || !st.hasMoreTokens())
					st = new StringTokenizer(r.readLine());
				return st.nextToken();
			} catch (Exception e) {
			}
			return null;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public long nextLong() {
			return Long.parseLong(next());
		}
	}
}

FastReaderWriter

java
package class019;

// 本文件课上没有讲
// java同学可以使用FastReader进行快读,可以使用FastWriter进行快写,速度是很快的
// 如何使用可以参考main函数

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.util.InputMismatchException;

public class Code06_FastReaderWriter {

	public static void main(String[] args) {
		FastReader reader = new FastReader(System.in);
		FastWriter writer = new FastWriter(System.out);
		System.out.println("输入一个字符:");
		int cha = reader.readByte(); // reader会读到字符的ASCII码
		System.out.println("输入一个int类型的数字:");
		int num1 = reader.readInt(); // reader会读到该数字
		System.out.println("输入一个long类型的数字:");
		long num2 = reader.readLong(); // reader会读到该数字
		System.out.println("打印结果:");
		writer.println(cha);
		writer.println(num1);
		writer.println(num2);
		writer.close();// close方法包含flush,会把结果刷出去
	}

	// 快读
	public static class FastReader {
		InputStream is;
		private byte[] inbuf = new byte[1024];
		public int lenbuf = 0;
		public int ptrbuf = 0;

		public FastReader(final InputStream is) {
			this.is = is;
		}

		public int readByte() {
			if (lenbuf == -1) {
				throw new InputMismatchException();
			}
			if (ptrbuf >= lenbuf) {
				ptrbuf = 0;
				try {
					lenbuf = is.read(inbuf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (lenbuf <= 0) {
					return -1;
				}
			}
			return inbuf[ptrbuf++];
		}

		public int readInt() {
			return (int) readLong();
		}

		public long readLong() {
			long num = 0;
			int b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}
			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}
	}

	// 快写
	public static class FastWriter {
		private static final int BUF_SIZE = 1 << 13;
		private final byte[] buf = new byte[BUF_SIZE];
		private OutputStream out;
		private Writer writer;
		private int ptr = 0;

		public FastWriter(Writer writer) {
			this.writer = new BufferedWriter(writer);
			out = new ByteArrayOutputStream();
		}

		public FastWriter(OutputStream os) {
			this.out = os;
		}

		public FastWriter(String path) {
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b) {
			buf[ptr++] = b;
			if (ptr == BUF_SIZE) {
				innerflush();
			}
			return this;
		}

		public FastWriter write(String s) {
			s.chars().forEach(c -> {
				buf[ptr++] = (byte) c;
				if (ptr == BUF_SIZE) {
					innerflush();
				}
			});
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) {
				return 19;
			}
			if (l >= 100000000000000000L) {
				return 18;
			}
			if (l >= 10000000000000000L) {
				return 17;
			}
			if (l >= 1000000000000000L) {
				return 16;
			}
			if (l >= 100000000000000L) {
				return 15;
			}
			if (l >= 10000000000000L) {
				return 14;
			}
			if (l >= 1000000000000L) {
				return 13;
			}
			if (l >= 100000000000L) {
				return 12;
			}
			if (l >= 10000000000L) {
				return 11;
			}
			if (l >= 1000000000L) {
				return 10;
			}
			if (l >= 100000000L) {
				return 9;
			}
			if (l >= 10000000L) {
				return 8;
			}
			if (l >= 1000000L) {
				return 7;
			}
			if (l >= 100000L) {
				return 6;
			}
			if (l >= 10000L) {
				return 5;
			}
			if (l >= 1000L) {
				return 4;
			}
			if (l >= 100L) {
				return 3;
			}
			if (l >= 10L) {
				return 2;
			}
			return 1;
		}

		public FastWriter write(long x) {
			if (x == Long.MIN_VALUE) {
				return write("" + x);
			}
			if (ptr + 21 >= BUF_SIZE) {
				innerflush();
			}
			if (x < 0) {
				write((byte) '-');
				x = -x;
			}
			int d = countDigits(x);
			for (int i = ptr + d - 1; i >= ptr; i--) {
				buf[i] = (byte) ('0' + x % 10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter writeln(long x) {
			return write(x).writeln();
		}

		public FastWriter writeln() {
			return write((byte) '\n');
		}

		private void innerflush() {
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush() {
			innerflush();
			try {
				if (writer != null) {
					writer.write(((ByteArrayOutputStream) out).toString());
					out = new ByteArrayOutputStream();
					writer.flush();
				} else {
					out.flush();
				}
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter println(long x) {
			return writeln(x);
		}

		public void close() {
			flush();
			try {
				out.close();
			} catch (Exception e) {
			}
		}
	}
}

全局静态空间

建议使用全局静态空间,递归返回后,在下次递归时空间可以复用,不用每次都去 new 一个空间,效率低