백준 자바 시간 초과 BufferedReader / StringTokenizer로 해결!

안녕하세요. 오늘은 백준을 풀다보면 평소 자바의 Scanner를 사용하는 것으로는 시간 초과가 뜨는 문제가 있습니다. 자바 기본서에서는 가르쳐주지 않을 것 같습니다. 시간 제한이 있는 알고리즘 문제 상 성능이 좋지않은 Scanner보다 BufferedReader를 쓰는게 나은 방향이겠죠.

 

 

정말 드라마틱한 속도 차이가 아니겠습니까? Scanner는 내부적으로 정규표현식을 돌리느라 성능이 낮은편이라고 합니다. 같은 느낌으로 Println의 속도도 굉장히 낮은편이니 나중에 다시 다뤄보겠습니다!

 

자 먼저, 버퍼라는게 뭐냐면 무언가를 저장해놓는 공간입니다. 버퍼를 사용하지않으면 즉시 입력이 되어버리겠죠.

 

BufferedReader는 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공 해주는 보조 스트림입니다.

 

자 먼저 import를 해와야겠죠.

여담이지만 이클립스의 Organize Import(기본 단축키 : Ctrl+Shift+O) 기능을 이용해서 필요한 import 구문을 가져올수도 있습니다. 
import java.io.BufferedReader;
import java.util.StringTokenizer;

 

public static void main(String[] args) throws IOException {

}

 

Scanner와 달리 BufferedReader는 try catch를 쓰던 throws Exception 쓰던 반드시 예외에 대한 처리를 해주어야합니다!

 

자 이제 조립을 해서 백준 4344번을 풀어봅시다. 

https://www.acmicpc.net/problem/4344

 

 

BufferedReader는 입력에서 한 줄을 통째로 읽기 때문에 읽어들인 문자열을 StringTokenizer을 통해 공백을 기준으로 분리해주어야 합니다.

 

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		// 먼저 BufferedReader와 StringTokenizer 객체를 만들어줍시다. 
		int arr[]; 
		//평균보다 키 큰 사람의 숫자를 구하기 위한 정수 배열도 만들어주고요.
		
		int C = Integer.parseInt(br.readLine()); 
		//입력한 값을 정수형으로 바꾸어 저장합시다. 왜냐면 버퍼드리더로 읽어온 것은 스트링이거든요!
		
		for (int i=0; i<C; i++) {
			st = new StringTokenizer(br.readLine()," "); 
			// 먼저 받아온 입력값을 공백단위로 나누어봅시다.
			int N = Integer.parseInt(st.nextToken());	
            // 학생 수를 받아와봅시다. 배열의 크기를 정할때도 사용하고 
            // 평균을 구할 때도 사용하거든요.
			arr = new int[N];
		
		
			double sum = 0; // 합을 구하기 위해 sum 선언해주시고
		
			for (int j=0; j<N; j++) {
				int val = Integer.parseInt(st.nextToken());
				sum += val;
				arr[j] = val;
			}	// 이제 반복문을 돌려서 합을 구해보고 점수를 배열에 넣기도 해봅시다.
				
			double mean = (sum / N) ; 
			//평균을 구하고
			double tallStudentNum = 0.0;
			//그 평균보다 큰 키를 가진 학생들을 선언해줍시다.
			
			for (int k=0; k<N; k++) {
				if (arr[k] > mean) {
					tallStudentNum++;
				}
			}
			
			// 자 이제 배열을 돌며 크기가 큰 사람을 찾아내봅시다.
			
			System.out.printf("%.3f%%\n", ( tallStudentNum / N ) * 100);
		
		
		}

	}

 

 

완료!