빠른 A+B

김나영·2023년 6월 15일
0

알고리즘

목록 보기
14/16

문제 : 빠른 A+B

풀이

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  • 문제에서 제시한 BufferedReader 사용

BufferedReader / BufferedWriter

  • 버퍼를 이용하여 읽고 쓰는 함수

  • 버퍼를 사용하기 때문에 Scanner와 System.out.println()과 비교했을 때 효율이 굉장히 좋아짐

1) BufferedReader

  • 문자열로 받게 되므로 형변환이 필요

  • 공백을 기준으로 값을 추출하기 위해 StringTokenizer 객체나 split()함수를 사용

  • 항상 IOException 예외처리를 해줘야함!

2) BufferedWriter

  • write() 메소드를 이용해 버퍼에 데이터 입력

  • flush() 메소드를 이용해 버퍼에 담긴 내용을 비우면서 출력

  • close() 메소드를 이용해 버퍼 종료

  • IOException 예외처리를 해줘야함!


public static void main(String[] args) throws IOException {
  • BufferedReader를 사용하려면 main 클래스 옆에 throws IOException(에외 처리)을 넣어줘야함
int T = Integer.parseInt(br.readLine());
  • 테스트케이스의 개수 T를 지정하고 readLine();이라는 메소드를 사용

  • BufferedReader는 readLine 즉, 한 줄을 받아오기 대문에 String 형태로 입력을 받아옴

  • BufferedReader는 String으로 리턴 값이 고정되어 있기 때문에, 다른 타입으로 입력을 받고자 한다면 반드시 형변환이 필요

  • String 값이 아닌 int 값을 입력 받아야하므로 Integer.parseInt를 사용해 int 타입으로 형변환을 시켜줌

StringBuilder sb = new StringBuilder();
  • String으로 값을 읽음(BufferedReader에 의해 String으로 입력 값을 받았기 때문에)

  • 시간 단축을 위해 사용


StringBuilder

  • 문자열을 배열처럼 관리하며 추가, 삭제, 삽입을 용이하게 하기 위해 사용

  • 여러 곳에서 동시에 같은 문자열 인스턴스에 접근할 때 중복 점유를 막을 수 있는 장치가 되어 있음

  • 배열 index를 이용하여 문자를 관리하는 클래스

자주 사용하는 함수

1) 추가

  • append() : StringBuilder에 추가

삭제

  • delete(from, to) : from부터 to까지 해당되는 index들을 제거 (to는 제외)

  • deleteCharAt(index) : index에 해당하는 문자 하나를 제거

삽입

  • insert(index, Object) : index위치에 Object를 추가

  • replace(from, to, String) : from, to 부분을 String으로 변경 (to는 제외)

  • setLength(len) : len만큼 길이를 변경 (len을 0으로 설정하면 내부가 비워지는 효과를 볼 수 있음)

  • setChar(index, char) : 해당 index를 char로 변경

  • reverse() : 문자열을 뒤집는 함수


for (int i = 1; i <= T; i++) {
    StringTokenizer st = new StringTokenizer(br.readLine());
    int A = Integer.parseInt(st.nextToken());
    int B = Integer.parseInt(st.nextToken());
    sb.append(A+B);
    sb.append("\n");
}
System.out.println(sb);
  • 각 케이스마다 A + B를 출력해야하므로 for문을 사용해 반복 출력

  • BufferedReader의 readLine()으로 받으면 문자열 자체로 받게 되므로 문자열을 분리해줘함

  • StringTokenizer 클래스를 통해 입력받은 문자열 reader.readLine()을 띄어쓰기를 기준으로 쪼개어 StringTokenizer 객체에 저장

  • 쪼개진 토큰을 nextToken() 메서드를 이용해 차례로 토큰을 읽음

  • A와 B는 정수이기 때문에 Integer.parseInt() 메서드를 사용해 int 타입으로 형변환

  • 구하고자하는 A + B, 줄바꿈을 뜻하는 개행문자("\n")를 sb에 저장(StringBuilder에서 추가할 때 사용하는 함수 append 사용)

  • for문 밖에서 sb 출력


StringTokenzier

  • 문자열을 구분자를 이용하여 분리할 때 사용할 수 있음(즉, 하나의 문자열을 여러 개의 토큰으로 분리)

  • BufferedReader 클래스만이 아니더라도 스페이스 기준 or 컴마(,) or 공백(" ")을 기준으로 문자열을 분리한다던가, 특정 문자에 따라 문자열을 나누고 싶을 때 사용

생성자

1) 띄어쓰기를 기준으로 문자열 분리

StringTokenizer st = new StringTokenizer(문자열);

2) 구분자를 기준으로 문자열 분리

StringTokenizer st = new StringTokenizer(문자열, 구분자);

3) true / false

StringTokenizer st = new StringTokenizer(문자열 , 구분자 , true/false);
  • 구분자를 기준으로 문자열을 분리할 때 구분자도 토큰으로 넣음(true)

  • 구분자를 분리된 문자열 토큰에 포함 시키지 않음(false)

  • 생성자 마지막 인자에 true/flase의 boolean 타입의 값을 넣어주는데, true라면 구분자도 토큰에 포함되고, false라면 구분자는 구분하는데만 쓰고 토큰에 포함되지 않음(디폴트는 false)


br.close();
  • BufferedReader를 사용하면 입출력이 끝난 뒤 close()로 닫아줘야함

  • BufferedWriter는 flush() 함수를 통해서 버퍼에 남아있는 데이터를 출력해 없앤 후, close()로 닫아줌

전체 코드

import java.io.*;
import java.util.StringTokenizer;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int T = Integer.parseInt(br.readLine());
        for (int i = 0; i < T; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int A = Integer.parseInt(st.nextToken());
            int B = Integer.parseInt(st.nextToken());
            sb.append(A+B);
            sb.append("\n");
        }
        System.out.println(sb);
        br.close();
    }
}

문제 발생

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        for (int i = 0; i < T; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine()," ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            System.out.println(a+b);
        }
        br.close();
    }
}
  • 시간 초과 발생

해결

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int T = Integer.parseInt(br.readLine());
        for (int i = 0; i < T; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int A = Integer.parseInt(st.nextToken());
            int B = Integer.parseInt(st.nextToken());
            sb.append(A+B);
            sb.append("\n");
        }
        System.out.println(sb);
        br.close();
    }
}
  • StringBuilder를 사용하여 해결

다른 방법의 풀이

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringBuilder sb = new StringBuilder();
        int T = Integer.parseInt(br.readLine());
        for (int i = 0; i < T; i++) {
            String[] Numbers = br.readLine().split(" ");
            int A = Integer.parseInt(Numbers[0]); // 첫 번째 호출
            int B = Integer.parseInt(Numbers[1]); // 두 번째 호출
            sb.append((A + B) + "\n");
        }
        bw.write(sb.toString()); // write에는 자동개행 기능 X => 개행문자 필수!!
        br.close();
        bw.flush();
        bw.close();
    }
}
  • BufferedWriter로 할당된 버퍼에 값을 넣어줌

  • Numbers라는 String 배열을 생성하여 split(" ")를 사용하여 공백마다 데이터를 끊어서 Numbers에 넣어줌

  • 배열은 [0]이 첫 번째, [1]이 두 번째 숫자

  • BufferedWriter는 출력이 가능하기 때문에 출력 함수 write를 사용하여 sb를 출력

  • StringBuilder는 toString() 메서드를 통해 출력

  • 버퍼를 잡아 놓았기 때문에 반드시 flush() / close()를 호출해 뒤처리를 해줘야함

0개의 댓글