hoon's bLog

백준 Java 백준 문제 풀이 시 주의 해야할 점 본문

코딩테스트/백준

백준 Java 백준 문제 풀이 시 주의 해야할 점

개발한기발자 2023. 3. 10. 19:44
반응형

 

내가 최근에 알고리즘 코딩 있는 사이트인 백준코딩!

하다 보니 약간(?)의 애로사항들이 있다.

고수이신 분들은 이게 왜? 라고 생각이 드실 수 있으나,

나 같은 자린이, 코민이들은 이런 부분에 상당 시간을 잡아먹는 경우가 있다.

때문에 나같은 피해자가 없길 바라며,

이 글을 써본다.

 

1. 제출시 클래스명은 Main, import 부분은 넣어주어야 한다.

  • 클래스명은 반드시 Main, 그리고 사용한 import는 반드시 함께 넣어주어야 함!
  • Main 이외의 클래스를 추가로 쓰고 싶으면 public이 아닌 클래스 혹은 inner 클래스로 사용
  • main문 자체가 static 함수이므로 거기서 사용하는 전역변수 및 모든 함수 또한 static이어야 한다.

아래 코드는 위의 규칙의 예시로 소스 제출 시 참고용 코드가 되겠다!

// package는 본인 프로젝트 경로이므로 제출시 반드시 제거
// package com.BaekjoonCode;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
    private int a = 0;
    private int b, c;

    //클래스 내부 함수 선언
    private void test(){
    	//input your code
    }

    //실제로 실행이 되는 main 함수
    public static void main(String[] args) throws Exception {
        //input your code
    }
}

3. Scanner 보다는 BufferReader 사용!

  • 일반적으로 Scanner sc = new Scanner(System.in); 을 통해 입력을 받지만, Scanner는 내부적으로 nextInt(), nextFloat() 등과 같이 이런 걸 호출 시 다음 입력을 찾기 위해 정규식을 사용하므로 느리다.
  • 이걸 쓰면 로직은 맞았는데도 시간 초과나서 틀리는 경우가 발생!!
  •  마찬가지로 String에 대한 split() 보다는 StringTokenizer로 짜르는게 더 빠르다. 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

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

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[] arr = new int[n];

        //문자열(br.readLine())을 받아 띄어쓰기 기준으로 문자열 분리
        StringTokenizer st = new StringTokenizer(br.readLine());
        //구분자를 기준으로 문자열 분리
        //StringTokenizer st = new StringTokenizer(br.readLine(), ",");

        int num = Integer.parseInt(br.readLine());
        int cnt = 0; 

        for(int i=0; i < arr.length; i++){
            arr[i] = Integer.parseInt(st.nextToken());
            if(arr[i] == num){
                cnt++;
            }
        }

        System.out.println(cnt);
        br.close();

    }
}

5. 입력을 위한 클래스는 하나만 쓸 것!

  • System.in 이 들어간 클래스는 단 하나만 생성하는 것이 좋다.
  • 각자의 IDE에서는 여러 개를 선언해도 크게 문제가 없을 것이다. 직접 입력할 것이므로 버퍼가 딱히 의미가 없다.
  • 하지만 백준 코딩문제의 경우 실제로 입력되는 건 파일로, Scanner나 BufferedReader나 둘 다 미리 일정량을 읽어 들인 후, 사용자의 요청(readLine() 등)에 따라 해당 버퍼에서 꺼내온다고 한다.
  • 따라서 이걸 여러개 선언해 버리면 이미 다른 클래스에서 버퍼에 쌓인 부분 때문에 제대로 읽을 수 없게 된다.

6. 출력도 System.out.println()은 느리다!

  • 마찬가지로 이것도 모르면 로직은 맞았는데 쓸데없이 출력이 느려서 시간초과가 날 수 있다.
  • (참고로 BufferedReader나 BufferedWriter 둘 다 깔끔하게 맨 끝에 close를 해주는 게 좋다.)
  • String의 '+' 연산 자체가 느리므로 빠른 출력을 쓰는 의미가 퇴색된다. 그렇다고 String.valueOf로 처리하자니 상당히 지저분하다.
  • StringBuilder로 출력할 것들을 전부 모아준 다음 그냥 System.out.println()으로 출력해 주는 방식으로 다음과 같다. 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public void main(String[] args) throws Exception{

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        int n = Integer.parseInt(br.readLine());
        
        for(int i=0; i < n; i++){
            StringTokenizer st = new StringTokenizer(br.readLine());
            int s = Integer.parsInt(st.nextToken());
            
            for(int j=0; j < s; j++){
                int data = Integer.parseInt(st.nextToken());
                sb.append(data).append('\n');
            }
        }
        
        System.out.println(sb);        
    }
}

프로그래밍 문제를 해결하면서 계속해서 업데이트할 예정이다.

관련된 자료들이 구글에 많이 있으나, 내가 정리를 또 하지 않으면,

또 찾는 수고와 구글링을 하면서의 공부가 반복될 것 같아 기록을 남긴다.

 

언제든지 좋은 질문과 지적, 태클 환영입니다!!!

 

끝:)

728x90
반응형