一次由 Scanner(System.in) 引起的 TLE

莫名其妙 TLE

  继昨天一次由 System.out.println() 引起的 MLE&TLE后,今天随机到一道快速选择的题(P1923),又遇到相似的问题,写完快速排序后修改几行代码就得到快速选择的代码,本以为轻松解决问题,然后又莫名其妙的 TLE

原始代码:

public static void main(String[] args) throws IOException {
	Scanner in = new Scanner(System.in);// 标准输入
	int n = in.nextInt();
	int k = in.nextInt();
	int[] a = new int[n];
	
	for (int i = 0; i < n; ++i) {
		a[i] = in.nextInt();
	}
	
	quickSelect(a, 0, n-1, k);// 快速选择
	System.out.println(a[k]);// 标准输出
	in.close();
}

第一次尝试结果:
在这里插入图片描述

举一反三

  有了昨天 System.out.println() 造成 MLE 的经验,很容易就想到是因为使用 Scanner(System.in) 标准输入性能低下造成的 TLE,于是进行改进。

// 使用 StreamTokenizer 替代Scanner in = newScanner(System.in);
StreamTokenizer in =
  new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

最终代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
	// StreamTokenizer对象
	public static StreamTokenizer in = 
			new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	// 由 Token获取 int
	public static int nextInt() throws IOException {
		in.nextToken();// 从输入流获取标记
		return (int)in.nval;// 转化
	}
	// 主函数
	public static void main(String[] args) throws IOException {
		int n = nextInt();// 自编写的读取整数函数
		int k = nextInt();
		int[] a = new int[n];
		for (int i = 0; i < n; ++i) {
			a[i] = nextInt();
		}
		quickSelect(a, 0, n-1, k);
		System.out.println(a[k]);
	}
}

最终结果:
在这里插入图片描述

总结

  • 使用 Scanner(System.in) 进行标准输出时,性能较差,不适合频繁调用。
  • 频繁输入调用使用 StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
  • 类 java.io.StreamTokenizer 可以获取输入流并将其分析为 Token(标记),使用 nextToken() 方法读取下一个标记。
  • 默认情况下,StreamTokenizer 认为下列内容是Token:字母数字除c和c++注释符号以外的其他符号
  • 使用 BufferedReader 创建 StreamTokenizer 对象以提高效率
  • 调用 nextToken() 方法从输入流中获取标记,调用 nextToken() 方法后,如果 Token 是字符串,可用 String s = st.sval 获取,如果是整数,可用 int x = (int)st.nval 获取。
posted @ 2021-11-21 08:15  Acx7  阅读(54)  评论(0编辑  收藏  举报